NSError 来对错误信息进行封装,它主要由3部分内容组成:
- domain 错误发生域
- code 错误码
- userInfo 详细信息
使用NSError对象,除了封装多种错误信息,还可以归档保存,以及继承后实现自定义行为。
Error Domain:
首先,error domain简称错误域,是一个字符串。通过 domain 属性,可以对 error 信息进行细分,domain 可以指明 error 对象代表的错误具体是发生在哪一层框架,除了指明层级的 domain,一个框架或某一模块的类都可以提供自己相关错误的 domain 用于分类,当然也包括自己实现的框架和类。另外,domain 相当于对下述代表具体错误原因的 code 提供了命名空间,避免了 code 的重复。
在OS X中将error分为不同的domain。譬如,对于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 NSErrorDomain const NSCocoaErrorDomain;
// Other predefined domains; value of "code" will correspond to preexisting values in these domains.
FOUNDATION_EXPORT NSErrorDomain const NSPOSIXErrorDomain;
FOUNDATION_EXPORT NSErrorDomain const NSOSStatusErrorDomain;
FOUNDATION_EXPORT NSErrorDomain const NSMachErrorDomain;
除了上述的四个domain之外,不同的framework定义了自己的domain,比如常见的网络请求URL定义了NSURLErrorDomain。
用户也可以为自己的framework或者app定义自己的domain,官方推荐的domain命名是:
com.company.framework_or_app.ErrorDomain,例如:com.baidu.baiduMap.errorDomain
code
NSInteger类型的 code 说明了 domain 下错误的具体原因。这个信息对于程序开发来说极为有用。比如访问URL资源timeout错误对应的是NSURLErrorTimedOut(-1001)。
iOS开发中常用的error code所对应的头文件如下:
//Generic Foundation错误代码
#import
#import
#import
例如NSURLErrorTimedOut错误码就是NSURLError.h库中的NSURLErrorDomain枚举code。
userInfo
// 预定义的userinfo键名
NSString *const NSUnderlyingErrorKey; //推荐的标准方式,通用键
NSString *const NSLocalizedDescriptionKey; // 详细描述键
NSString *const NSLocalizedFailureReasonErrorKey; // 失败原因键
NSString *const NSLocalizedRecoverySuggestionErrorKey; //恢复建议键
NSString *const NSLocalizedRecoveryOptionsErrorKey; // 恢复选项键
//其他键
NSString *const NSRecoveryAttempterErrorKey;
NSString *const NSHelpAnchorErrorKey;
NSString *const NSStringEncodingErrorKey ;
NSString *const NSURLErrorKey;
NSString *const NSFilePathErrorKey;
通过 error 对象的 userInfo 字典,可以包含一些其他的自定义信息。NSError类内置了几个关于本地化描述错误的 key,除了根据 key 从 userInfo 中取值外,NSError还提供了对应的只读属性来直接读取相关信息。当创建 error 对象时,应该在 userInfo 内也提供这几项内容。
description
通过属性localizedDescription获取 key 为NSLocalizedDescriptionKey中的内容,该项是错误的描述内容,可能包含 failure reason。failure reason
通过属性localizedFailureReason获取 key 为NSLocalizedFailureReasonErrorKey中的内容,该项是错误原因的解释。recovery suggestion
通过属性localizedRecoverySuggestion获取 key 为
NSLocalizedRecoverySuggestionErrorKey中的内容,该项描述了用户如何操作以修复错误。-
recovery options
通过属性localizedRecoveryOptions获取 key 为
NSLocalizedRecoveryOptionsErrorKey中的内容,该项是一个字符串数组,内容是提供给用户操作的按钮的标题,与 recovery suggestion 配合使用,默认的顺序规则是,第一个字符串应该用于最右边的按钮,以此类推。
下图展示了上述几项属性的关系
recoveryAttempter
获取 userInfo 中 key 为NSRecoveryAttempterErrorKey的值,该值是一个实现了NSErrorRecoveryAttempting协议的实例,与 recovery options 配合使用,可以让系统根据用户选择点击的按钮,执行相应的修复方法,但只能在 Cocoa 框架中使用。helpAnchor
获取 userInfo 中 key 为NSHelpAnchorErrorKey的值,用于 Cocoa 框架中,
NSAlert类执行方法+ alertWithError:时,展示的错误提示框中 help anchor button 的标题。
NSError 对象的创建
//两种初始化方法:其中,domain 不能为空 dict可以为空
- (instancetype)initWithDomain:(NSErrorDomain)domain code:(NSInteger)code userInfo:(nullable NSDictionary *)dict NS_DESIGNATED_INITIALIZER;
+ (instancetype)errorWithDomain:(NSErrorDomain)domain code:(NSInteger)code userInfo:(nullable NSDictionary *)dict;
下面写了一个自定义的NSError的demo作为参考
NSError+Common.h
#import
NS_ASSUME_NONNULL_BEGIN
//domain
FOUNDATION_EXPORT NSString *const NSCommonErrorDomain;
/**错误状态码*/
typedef NS_ENUM(NSInteger,NSCommonErrorCode){
NSCommonErrorCodeUnKnow = -1000,
NSCommonErrorCodeSucc = -1001,
NSCommonErrorCodefailed = -1002,
};
@interface NSError (Common)
+(NSError*)errorCode:(NSCommonErrorCode)code;
+(NSError*)errorCode:(NSCommonErrorCode)code userInfo:(nullable NSDictionary*)userInfo;
@end
NS_ASSUME_NONNULL_END
NSError+Common.m
#import "NSError+Common.h"
NSString *const NSCommonErrorDomain = @"NSCommonErrorDomain";
@implementation NSError (Common)
+(NSError*)errorCode:(NSCommonErrorCode)code{
return [self errorCode:code userInfo:nil];
}
+(NSError*)errorCode:(NSCommonErrorCode)code userInfo:(nullable NSDictionary*)userInfo{
if (userInfo) {
return [NSError errorWithDomain:NSCommonErrorDomain code:code userInfo:userInfo];
}else{
return [NSError errorWithDomain:NSCommonErrorDomain code:code userInfo:
@{
NSLocalizedDescriptionKey:@"返回的消息?",
NSLocalizedFailureReasonErrorKey:@"失败原因",
NSLocalizedRecoverySuggestionErrorKey:@"意见:恢复初始化",
@"自定义":@"自定义的内容",
}];
}
}
@end