在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 錯誤處理 - Dealing with Errors
使用對象 - Working with Objects
使用塊 - Working with Blocks
自定義現(xiàn)有的類 - Customizing Existing Classes
使用協(xié)議 - Working with Protocols
定義類 - Defining Classes
賦值與集合 - Values and Collections
關于 Objective-C
命名規(guī)則 - Conventions
錯誤處理 - Dealing with Errors
數(shù)據(jù)封裝 - Encapsulating Data

錯誤處理 - Dealing with Errors

幾乎所有的 APP 都會出現(xiàn)錯誤。一些錯誤可能會在你的可控范圍之外,例如硬盤空間耗盡或者網(wǎng)絡連接中斷。另一些錯誤卻是可恢復的,例如無效用戶輸入。當開發(fā)者在不斷追逐完美的過程中,也可能會伴隨著偶爾的編程錯誤的出現(xiàn)。 如果你來自于其他的語言和開發(fā)平臺,你也許會習慣于處理大多數(shù)錯誤處理中的異常。當你用 ObjC 編程的時候,異常僅會出現(xiàn)在編程錯誤中,就像數(shù)組越界訪問或無效方法參數(shù)。這些就是在你的 APP 上線前的測試中,你需要排查并修復的問題。 NSError 類的實例代表了所有其他的錯誤。這一章我們將簡單的介紹一下 NSError 對象的使用,包括怎樣處理構造方法可能出現(xiàn)的失敗和返回錯誤。更多信息參見?Error Handling Programming Guide

對大多數(shù)的錯誤使用 NSError

錯誤是任何APP 生命周期中不可避免的一部分,假設你需要向一個遠程網(wǎng)絡服務器請求數(shù)據(jù),在這個過程中有多種潛在問題可能出現(xiàn),包括:

  • 無網(wǎng)絡連接
  • 遠程網(wǎng)絡服務器不可訪問
  • 遠程網(wǎng)絡服務器不能提供你請求的信息
  • 得到的數(shù)據(jù)與你期望的不匹配
  • 遺憾的是,建立所有可能問題的應急計劃與方案是不現(xiàn)實的。相反你必須為可能出現(xiàn)的錯誤籌劃并且知道如何解決,從而獲得最好的用戶體驗。

一些授權方法( delegate method )向你提醒錯誤

如果你正實現(xiàn)一個授權對象,它是與一個執(zhí)行某任務的構造類( framework class )一起使用的,比如這個對象需要從遠程服務器上下載信息。通常,你會發(fā)現(xiàn)你需要至少實現(xiàn)一個錯誤關聯(lián)方法(error-related method)。例如 包括了一個 connection:didFailWithError:? 方法的NSURLConnectionDelegate 協(xié)議:

    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

當一個錯誤發(fā)生時,授權方法將會被調用,以向你提供一個 NSError 對象來描述這個錯誤。 一個NSError對象包含一個數(shù)字錯誤代碼,域名和描述,以及封裝在一個用戶信息字典里的其他相關信息。 比起做出讓所有可能錯誤都具有唯一的數(shù)字代碼的要求,Cocoa 和 Cocoa Touch 的錯誤被劃分成域。例如一個錯誤發(fā)生在?NSURLConnection 中,NSURLErrorDomain 域中的? connection:didFailWithError: 方法將會報一個錯。錯誤對象還包含一個本地化的描述,例如“找不到指定主機名的服務器”。

一些方法可以通過引用傳遞錯誤

一些Cocoa 和 Cocoa Touch 的API 通過引用傳回錯誤,舉個例子,你可能決定通過 ?NSData? 的 ?writeToURL:options:error: 方法,將你從網(wǎng)絡服務器獲得的信息通過存入硬盤的形式保存下來。這個方法的最后一個參數(shù)是一個指向 NSError 指針的引用。

    - (BOOL)writeToURL:(NSURL *)aURL
    options:(NSDataWritingOptions)mask
    error:(NSError **)errorPtr;

在你調用這個方法之前,你需要創(chuàng)建一個合適的指針來傳遞地址:

    NSError *anyError;
    BOOL success = [receivedData writeToURL:someLocalFileURL
                                    options:0
                                    error:&anyError];
    if (!success) {
    NSLog(@"Write failed with error: %@", anyError);
    // present error to user
    }

當錯誤發(fā)生時,writeToURL:options:error: 方法會返回 NO ,并會更新你的 anyError指針,指向一個錯誤類來描述出現(xiàn)的問題。在處理應用傳遞的錯誤時,重要的是去檢測方法的返回值以確定是否有錯誤發(fā)生。不要只是測試是否有設置指向錯誤的指針。

提示: 如果你并不關心出錯的對象,則只需要將 NULL 傳遞給 error: 參數(shù)

如果可以,盡量將錯誤恢復或顯示給用戶

對你的 APP 來說最好的用戶體驗是隱蔽地從錯誤中恢復。例如,你正在向遠程網(wǎng)絡服務器發(fā)出請求,如果此時發(fā)生了錯誤,你可以試著再向另一個服務器發(fā)送請求,或者你可以向用戶請求更多的信息,比如有效的用戶名和密碼,然后再次發(fā)出請求。 當從錯誤中恢復是不可能的時候,你才應該去警告用戶。如果你正在使用 iOS的Cocoa Touch進行開發(fā),你需要創(chuàng)建一個 UIAlertView 并調節(jié)它,從而向用戶顯示錯誤。如果你正在使用 OS X 的 Cocoa ,你可以在任何一個 NSResponder 對象(像是一個界面、窗口甚至是應用程序對象本身)上調用? presentError:? ,然后這個錯誤便會被傳輸?shù)巾憫溕?,以進行進一步的調試或恢復。當它到達應用程序對象時,應用程序會通過一個警告板將錯誤呈現(xiàn)給用戶。更多關于向用戶呈現(xiàn)錯誤,參看?Displaying Information From Error Objects

生成你自己的錯誤信息

為創(chuàng)建你自己的 NSError 類,你需要通過以下格式定義你自己的錯誤類:

    com.companyName.appOrFrameworkName.ErrorDomain

你需要為每一個可能發(fā)生在你的錯誤域中的錯誤選擇一個唯一的錯誤編碼,同時還有合適的錯誤描述,關于錯誤的描述將會被存儲在用戶信息字典中。像下面這樣:

    NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
    NSString *desc = NSLocalizedString(@"Unable to…", @"");
    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };

    NSError *error = [NSError errorWithDomain:domain
                                         code:-101
                                     userInfo:userInfo];

這個例子使用了 NSLocalizedDescriptionKey 函數(shù)來查看來自 ?Localizable.strings 文件中,錯誤描述的本地化版本,即在本地化字符串資源中描述的那樣。

如果你需要像早前描述的那樣,通過引用將錯誤傳回,你的方法標識中還需要包含一個為指針設置的參數(shù),用來指向一個 NSError 對象。你同時還需要利用返回的值指明是成功還是失敗,像是這樣:

    - (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr;

當錯誤發(fā)生時,在返回表示失敗的NO之前,你需要首先檢查為錯誤參數(shù)提供的指針值是否為空( NULL ),然后才能取消引用來設置錯誤信息:

    - (BOOL)doSomethingThatMayGenerateAnError:(NSError **)errorPtr {
    ...
    // error occurred
    if (errorPtr) {
        *errorPtr = [NSError errorWithDomain:...
                                        code:...
                                    userInfo:...];
      }
       return NO;
    }

用于編程錯誤的異常

ObjC 用與其他編程語言類似的方式支持異常,并且與這些語言,如 C++ 、Java ,支持的語法也很相似。就像 NSError 一樣,在 Cocoa 和 Cocoa Touch 里的異常,也是以 NSException 類實例為代表的對象。 如果你編寫的代碼可能導致異常拋出,你可以將這段代碼封裝在一個 try-catch 塊內:

     @try {
        // do something that might throw an exception
    }
    @catch (NSException *exception) {
        // deal with the exception
    }
    @finally {
        // optional block of clean-up code
        // executed whether or not an exception occurred
    }

如果異常拋出發(fā)生在 @try 塊內,那么它將會被 @catch 塊捕捉,以方便你對它的處理。比如你在用使用異常作為錯誤處理的低級別C++ 庫進行開發(fā),你可能會捕捉到異常,并生成一個合適的 NSError 對象以向用戶顯示異常。

如果一個異常被拋出但并未被捕獲,那么默認的未捕捉異常處理器(?uncaught exception handler )將會加載一個可以控制并終止應用的消息。

你不應該使用 try-block 塊來代替 ObjC 的標準程序檢測,以 NSArray 為例,你應該總是先使用數(shù)組的數(shù)目( count )來確定元素的數(shù)量,然后才通過給定索引訪問一個對象。如果你發(fā)出了越界訪問請求,那么 objectAtIndex: 方法將會拋出一個異常,這樣你就可以在早期的開發(fā)過程中及時發(fā)現(xiàn) bug ——你應該盡量避免在你已經(jīng)上線的 APP 中出現(xiàn)異常拋出。 更多關于 ObjC 應用中的異常,參看?Exception Programming Topics