寫在前面
在iOS開發中,NSError的使用非常常見,使用也比較簡單,也正因為簡單,所以對這一部分知識不甚注重。但是近期在做app底層網絡封裝時發現了一些問題。我使用的網絡框架是AFNetworking,AFNetworking常常會返回一些錯誤信息,有時需要將這些錯誤信息告訴用戶,通常做法是將error.localizedDescription以彈框的形式原原本本展現給用戶(譬如“網絡不暢”之類的),但是這樣非常不友好,一是這些信息往往是英文,二是這些信息過于冗長,不夠簡潔。所以自然想到了對這些error信息進行包裝。這就迫使我不得不去了解更多關于NSError相關的信息,本文著重敘述Error Domain和Error Code。
Error Domain
首先,error domain是一個字符串。因為歷史原因,在OS X中將errors分為不同的domains。譬如,對于Carbon框架的Error,歸于OSStatus domain(NSOSStatusErrorDomain),對于POSIX error,歸于NSPOSIXErrorDomain,而對于我們的iOS開發,一般使用NSCocoaErrorDomain。NSError.h定義了四個domain,如下:
// Predefined domain for errors from most AppKit and Foundation APIs.
FOUNDATION_EXPORT NSString *const NSCocoaErrorDomain;
// Other predefined domains; value of "code" will correspond to preexisting values in these domains.
FOUNDATION_EXPORT NSString *const NSPOSIXErrorDomain;
FOUNDATION_EXPORT NSString *const NSOSStatusErrorDomain;
FOUNDATION_EXPORT NSString *const NSMachErrorDomain;
除了上述的四個domain之外,不同的framework甚至一些classes group(相關的幾個classes)也定義了自己的domain,譬如對于Web Kit framework,定義了WebKitErrorDomain,而更常見的,URL相關的classes定義了NSURLErrorDomain。
Domains非常有用,特別當程序非常復雜龐大時,官方文檔是這么說的:
Domains serve several useful purposes. They give Cocoa programs a way to identify the OS X subsystem that is detecting an error. They also help to prevent collisions between error codes from different subsystems with the same numeric value. In addition, domains allow for a causal relationship between error codes based on the layering of subsystems; for example, an error in the NSOSStatusErrorDomain may have an underlying error in the NSMachErrorDomain.
用戶也可以為自己的framework或者app定義自己的domain,官方推薦的domain命名是:
com.company.framework_or_app .ErrorDomain
Error Code
Error Code的類型是signed integer。Error Code指定了特殊的錯誤。這個信息對于程序開發來說極為有用。比如訪問URL資源timeout錯誤對應的是NSURLErrorTimedOut(-1001)。
那么如何知道各個error code對應什么樣的值呢?iOS開發中常用的error code所對應的頭文件如下:
- <Foundation/FoundationErrors.h> -- Generic Foundation error codes
- <CoreData/CoreDataErrors.h> -- Core Data error codes
- <Foundation/NSURLError.h> -- URL error codes
以Foundation/NSURLError.h為例,其中的URLError Code值從NSURLErrorDataLengthExceedsMaximum到NSURLErrorCancelled,二者分別對應-1103和-999。如果對所有網絡error籠統處理,這兩個值可以為我所用。
The User Info Dictionary
Every NSError object has a “user info” dictionary to hold error information beyond domain and code.
user info
可以包含很多自定義信息,最常用的或許是localized error information
。訪問localized error information
有兩種方式,其一是訪問error的localizedDescription屬性,其二是訪問error.userInfo的NSLocalizedDescriptionKey域。
關于user info dictionary,比較常見,這里不多講了,更多內容參考:
《Error Handling Programming Guide》