> 文章列表 > NSError是什么 ?

NSError是什么 ?

NSError是什么 ?

在这里插入图片描述

为什么要创造 NSError ?

Unix 系统中所有的程序都是其他进程的子进程,从原始进程一路 fork 出来,即那个不为所动的发起者:pid 1 (OS X 系统中是 launchd)。当可执行文件结束时,它用一个 0 到 255 状态码与父进程通信,告诉它程序为什么或怎么退出的。0 意味着“一切正常退出;没有可通告的”,非零值表示发生了父进程需要注意的事。退出状态码可以用来表示进程是否崩溃,或者提前终止。按照惯例,越大的值,引发的错误越严重。

在面向对象编程范式中,大部分进程被抽象出来,只剩下对象及它们之间传递的消息。但是成功还是失败(以及不同种类的失败)在面向对象编程中仍然十分有用。而表示 “成功还是失败” 的方法如果只是返回 BOOL 类型的值,这通常会造成某种困境(predicament),尤其是失败的情况下(你无法确认为什么会失败)。所以 NSError 被创造出来。

与其它语言相比

那些比 Objective-C 更小题大做更好战的语言通过滥用异常来调解这个问题,哪怕一点点的不合规也抛异常。不过作为果粉幸运的是,当有坏事发生时 Objective-C 使用一种更文雅的方式,那便是 NSError。

相比于无可奈何地抛出异常,将这些信息包装在一个类似于 NSError 这样的对象中的优势在于,这些错误对象可以很容易的在不同对象及上下文中传递。

初识 NSError

  1. 归属于 Foundation 框架, 是 Core Foundation 中 CFError 的无缝转换 ( toll-free bridged ) 对象。
  2. 每个 NSError 对象编码了三部分关键信息:
    • code - 状态码;
    • domain - 对应的特定错误域;
    • userInfo - 额外的通过 Dictionary 提供的上下文 ( context );

To err is human. To NSError is Cocoa.


Code & Domain

code 表示问题的本质, 多个 code 对应于一个特定的( particular )错误域,即此处的 domain, 这可以有效地避免重叠和混淆(overlap and confusion)。code天然地适合用 enum 来定义,Cocoa 中使用的是 NS_ERROR_ENUM(...),优势在于在定义的同时就直接指定了所属的错误域。它们的详细定义如下:

typedef NSString *NSErrorDomain;
/* These define the error. * Domains are described by names that are arbitrary strings used to differentiate groups of codes;    * for custom domain using reverse-DNS naming will help avoid conflicts. Codes are domain-specific.*/
@property (readonly, copy) NSErrorDomain domain;
@property (readonly) NSInteger code;

userInfo

是什么给了 NSError 它独特的魅力?正是这个每个人都喜欢的大杂烩属性:userInfo。作为整个 Cocoa 的惯例,userInfo 是一个可以包含任意键值对的字典,无论是为了继承或降低耦合的目的, 它都不适合拿来填满各种杂七杂八的属性。

在 NSError 这个例子中,有一些特定的键值对应着只读属性。它们通常是很有用的:

  • localizedDescription (NSLocalizedDescriptionKey): 一段本地化的错误描述。
  • localizedRecoverySuggestion (NSLocalizedRecoverySuggestionErrorKey): 一段该错误的恢复建议。
  • localizedFailureReason (NSLocalizedFailureReasonErrorKey): 一段本地化的错误解释。

完整的标准 NSError - userInfo 键列表,在需要时可以自行查询。