NSError用法靈活,經由此對象,我們可以把導致錯誤的原因回調給調用者。NSError對象里封裝了三條信息:
1)Error domain:錯誤范圍,其類型為字符串
錯誤發生的范圍,也就是產生錯誤的根源,通常用一個特有的全局變量來定義。比方說,“處理URL的子系統”在從URL中解析或者取得數據時如果出錯了,那么就會使用NSURLErrorDomain來表示錯誤范圍。
2)Error code:錯誤碼,其類型為整數
獨有的錯誤代碼,用以指明在某個范圍內具體發生了何種錯誤。某個特定的范圍內可能會發生一系列相關錯誤,這些錯誤情況通常采用enum來定義。例如當http請求出錯時,可能會把http狀態碼設為錯誤碼。
3)User info:用戶信息,其類型為字典
有關此錯誤的額外信息,其中或許包含一段“本地化的描述”,獲取還含有導致該錯誤發生的另外一個錯誤,經由此種信息,可將相關錯誤串成一條“錯誤鏈”。
NSError常見用法:
- (BOOL)doSomething:(NSError**)error
參數是個指針,該指針又指向另外一個指針,那個指針指向NSError對象。或者也可以把它當成一個直接指向NSError對象的指針。這樣以來此方法不僅能有普通的返回值,而且還能把NSError對象回傳給調用者。其用法如下:
NSError *error = nil;
BOOL ret = [object doSomething:&error];
if (error) {
//there was a error
}
像這樣的方法一般都會返回BOOL值,用以表示該操作是成功了還是失敗了。如果調用者不關心具體錯誤信息那么直接判斷這個bool值就好。
實際上在使用ARC的時候,編譯器會把方法簽名中的NSError**轉換成NSError*__autoreleasing*,也就是說,指針所指的對象會在方法執行完畢后自動釋放。這個對象必須自動釋放,因為“doSomething:”不能保證其調用者可以把此方法中創建的NSError釋放掉,所以必須加入autorelease。
該方法通過下列代碼把NSError對象傳遞到“輸出參數”中:
- (BOOL)doSomething:(NSError**)error {
//Do something
if (/*there was an error*/) {
if (error) {
*error = [NSError errorWithDomain:domain code:code userInfo:userInfo];
}
return NO;
}else {
return YES;
}
}
這段代碼以*error語法為error參數“解引用”,也就是說,error所指的那個指針現在要指向一個新的NSError對象了,在解引用之前必須先保證error參數不是nil,因為空指針解引用會導致“段錯誤”並使應用程序崩潰。調用者在不關心具體錯誤時,會給error參數傳為nil,所以必須判斷這種情況。
NSError對象里的“錯誤范圍”、“錯誤碼”、“用戶信息”等部分應該按照具體的錯誤情況填入適當內容。這樣的話調用者就可以根據錯誤類型分別處理各種錯誤了。例如,可以把這些值定義成下面這樣:
.h
extern NSString *const ErrorDomain;
typedef NS_ENUM(NSUInteger, Error) {
ErrorUnknow = -1,
ErrorInternalInconsistency = 100,
};
.m
NSString *const ErrorDomain = @"ErrorDomain";
要點:
1)只有發生了可使整個應用程序崩潰的嚴重錯誤時,才應使用異常。
2)在錯誤不那么嚴重的情況下,可以指派“委托方法”來處理錯誤,也可以把錯誤信息放在NSError對象里,經由“輸出參數”返回給調用者。