NSError了解一哈
说来惭愧,工作以来一直没有好好了解NSError
这个类。这次的话因为一些需求,准备系统的学习一下子,下面就是我大致的总结。
综述
OC中通常使用NSError
对象来发出错误信号,提供错误类型以及任何潜在原因的额外信息。
Foundation
和其它Cocoa
框架产生的错误通常归属于NSCocoaErrorDomain
错误域。NSCocoaErrorDomain
中的错误状态码都是在Foundation
定义好的常量。
在子类中,可以通过覆写localizedDescription
方法来提供更好的本地错误描述。
NSError
是CFError
的无缝转换对象。
每个NSError
对象主要提供三部分的信息:
- code 状态码
- domain 对应的特定错误域
- userInfo 额外的信息
code和domain
code
状态码表示问题的本质,这些状态码都在一个特定的错误域中,以防重叠和混淆。
例如在NSCocoaErrorDomain
中,NSFileManager
访问一个不存在的文件产生的错误代码是4。而在NSPOSIXErrorDomain
中,4代表中断函数
错误。
userInfo及一些属性
作为Cocoa
的惯例,userInfo
是一个可以包含任意键值对的字典,无论是为了继承或降低耦合的目的, 它都不适合拿来填满各种杂七杂八的属性。在NSError
这个例子中,有一些特定的键值对应着只读属性。一下是标准NSError
的userInfo
的键列表
- NSLocalizedDescriptionKey
- NSLocalizedFailureReasonErrorKey
- NSLocalizedRecoverySuggestionErrorKey
- NSLocalizedRecoveryOptionsErrorKey
- NSFilePathErrorKey
- NSStringEncodingErrorKey
- NSUnderlyingErrorKey
- NSRecoveryAttempterErrorKey
- NSHelpAnchorErrorKey
下面是常见的几个键:
localizedDescription
NSLocalizedDescriptionKey的对应值,即userInfo[NSLocalizedDescriptionKey],下同
一段本地化的错误描述。错误的主要可呈现信息。例如NSFileReadNoPermissionError
:”文件XX无法打开,因为你并没有查看它的权限”。理想状况下,这个信息会指出失败的原因以及失败原因。这个值来自于NSLocalizedDescriptionKey
或者是NSLocalizedFailureErrorKey + NSLocalizedFailureReasonErrorKey
或者是NSLocalizedFailureErrorKey
。构建描述信息的步骤如下:
- 在
userInfo
中查找NSLocalizedDescriptionKey
,如果存在则使用 - 在
userInfo
中查找NSLocalizedFailureErrorKey
,如果存在,则使用,与NSLocalizedFailureReasonErrorKey
的值组合使用(如果存在) - 在
userInfoValueProvider
中查找NSLocalizedDescriptionKey
,如果存在则使用 - 在
userInfoValueProvider
中查找NSLocalizedFailureErrorKey
,如果存在则使用,与NSLocalizedFailureReasonErrorKey
的值组合使用(如果存在) - 在
userInfo
或者userInfoValueProvider
查找NSLocalizedFailureErrorKey
,如果存在则使用
上文中提到的
userInfoValueProvider
我也不知道是什么东西,我猜测可能是NSError的类方法+ (id _Nullable (^)(NSError * _Nonnull, NSErrorUserInfoKey _Nonnull))userInfoValueProviderForDomain:(NSErrorDomain)errorDomain;
中的返回值
localizedRecoverySuggestion
NSLocalizedRecoverySuggestionErrorKey的对应值,即userInfo[NSLocalizedRecoverySuggestionErrorKey],一段该错误的恢复建议,适合在
alert
中显示为辅助消息。
localizedFailureReason
localizedFailureReason的对应值,即userInfo[localizedFailureReason],一段本地化的错误解释
如何使用调用系统API时返回的NSError
了解过上面的知识之后,那我们要怎样更好的使用系统返回给我们的NSError
呢,下面是我自己使用的方式:
1 | - (void)showErrorDetail:(NSError *)error viewController:(UIViewController *)viewController |
如何创建一个NSError
作为开发者,我们需要怎么样使用NSError
,才能更好的传递错误信息呢?首先,我们可以按Foundation
库中很多类那个样子,在一个自定义方法中定义NSError **
类型的形参。然后,我们也可以定义属于自己的错误域、错误代码常量和userInfo中的Key。
1 | // 自定义Domain |
使用userInfo字典来创建一个NSError
1 | NSDictionary *userInfo = @{ |
将错误信息包装在NSError
对象中,很容易在不同对象或者上下文中进行传递。
结束
参考来源:
- NSError
- 苹果文档
NSError了解一哈