21、理解Objective-C错误模型
Error对象里封装了三条信息:
Error domain:错误范围,字符串
产生错误的根源,通常用一个特有的全局变量来定义。如:
NSURLError表示解析URL出错Error code:错误码,整数
独有的错误码,指明在某个范围内具体发生了何种错误,通常用enum定义。如:HTTP请求出错时,可能回把HTTP的状态码设为错误码
User info:用户信息,字典
有关此错误的额外信息,其中或许包含一段“本地化的描述”(localized description),或许还含有导致该错误发生的另外一个错误,经由此种信息,可将相关错误串成一条“错误链”(chain of errors)
通过“委托协议”传递错误
有错误放生时,当前对象会把错误信息经由协议中的某个方法传递给其
delegate委托对象,如: 当
NSURLConnection出错后(比如与远程服务器的链接操作超时了),就回调用此方法以处理相关错误:- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { DDLogDebug(@"connection didFailWithError %@", error); } 这个委托方法未必非得实现不可:是不是必须处理此错误,可交由
NSURLConnection类的用户来判断。(这比抛出异常要好,因为调用者至少可以自己决定是否需要处理该错误)通过方法的“输出参数”传递错误
如:
// 传入的是一个指针的内存地址(因为change的是:指针重指向,而不是修改指向的内容) - (BOOL)doSomething:(NSError **)error { if (/* 有错误*/) { if (error) { // 必须判断 // *error: 为error参数“解引用”(dereference),及error所指的那个指针现在要指向一个新的NSError对象了。 *error = [NSError errorWithDomain:domain code:code userInfor:dic]; // 在解引用之前必须保证error参数不是nil // 因为空指针解引用会导致carsh:“段错误”segmentation fault } } } // 使用: // 1.在乎error NSError *error = nil; BOOL result = [object doSomething:&error]; if (error) { // 处理error } // 2.不在乎error BOOL result = [object doSomething:nil]; if (!result) { // 处理error }像这样的方法一般返回Boolean值,表示该操作成功 or 失败。如果调用者不关注估计的错误信息,则直接判断该Boolean值就好了;若关注具体错误,那就检查经由“输出参数”所返回的那个错误对象。
NSError的domain、code、userInfor应该根据具体错误情况填入适当内容,方便调用者根据错误类型分别处理各错误。domain定义成NSString类型的全局常量,而code则定义成枚举类型为佳。如:
// XXXErrors.h
extern NSString *const XXXErrorDomain;
typedef NS_ENUM(NSUInteger, XXXError) {
XXXErrorUnKnown = -1,
XXXErrorGeneralFault = 100,
XXXErrorBadInput = 101,
}
// XXXErrors.m
NSString *const XXXErrorDomain = @"XXXErrorDomain";建议:
为自己的程序库中所发生的错误制定一个专用的“错误范围”字符串
用枚举定义错误码,不仅解释错误码的含义,还给它们起了个有意义的名字
要点:
只有发生了会使整个应用程序崩溃的严重错误时,才使用异常
在错误不那么严重的情况下,可以指派“委托方法”(delegate method)来处理错误,也可以把错误信息放在
NSError对象里,经由“输出参数”返回给调用者
Last updated
Was this helpful?