最佳实践 - 在您自己的项目/应用中使用NSError domains和codes

117

关于为自己的框架设置错误域名,有一个之前的SO帖子,但是在自己的项目/应用中设置错误域和自定义错误代码的最佳实践是什么?

例如,假设您正在开发一个使用大量验证的Core Data密集型应用程序,您应该坚持使用“现成的”Core Data错误代码(例如CoreDataErrors.h中的NSManagedObjectValidationError),还是应该创建自己的MyAppErrors.h并定义更具体的错误(即MyAppValidationErrorInvalidCombinationOfLimbs)?

创建自定义错误域和一组错误代码可以显着消除您的代码中的歧义,但这是否会产生过多的维护开销,并且是否需要担心错误代码编号冲突?或者还有其他问题需要考虑吗?

3个回答

154

我个人使用反向域名系统的域名命名方式。例如:

NSError * myInternalError = [NSError errorWithDomain:@"com.davedelong.myproject" code:42 userInfo:someUserInfo];

域名的第三部分(@"myproject")只是用于区分此项目("My Project")中的错误和另一个项目("My Other Project" => com.davedelong.myotherproject)中的错误。
这是一种简单的方法,以确保我不会与其他人的错误域发生冲突(如果我使用第三方代码),除非那个开发者有意地试图干扰我(我认为这可能性极小...)。
至于代码编号冲突,不要担心。只要代码在域内唯一,就应该没问题。
至于翻译错误,那取决于你。无论你做什么,都要确保你对其进行了充分的文档记录。个人而言,我通常只是将框架生成的错误原样传递,因为我从来不确定我是否会处理所有代码并将所有userInfo转换为更具体的内容与我的项目相关。框架可能会更改并添加更多代码,或更改现有代码的含义等。它还帮助我更具体地确定错误来源。例如,如果我的StackKit框架在com.stackkit域中生成错误,则我知道这是一个框架问题。但是,如果它在NSURLErrorDomain中生成错误,则我知道它特别来自于URL加载机制。
你可以捕获框架生成的错误,并将其封装在一个新的错误对象中,该对象具有你的域和通用代码,例如"kFrameworkErrorCodeUnknown",然后将捕获的错误放置在"userInfo"下的"NSUnderlyingErrorKey"中。CoreData经常这样做(例如,如果你尝试保存"NSManagedObjectContext",但存在关系完整性错误,则会返回一个单个错误,但"NSUnderlyingErrorKey"将包含更多信息,例如哪些关系是错误的等)。

由于苹果公司也使用反向DNS,因此其他人使用这种风格似乎是合适的。 - Johan Karlsson

39

我没有足够的声誉来发表评论,但对于Dave DeLong提供的答案,最好使用[[NSBundle mainBundle] bundleIdentifier]而不是@"com.myName.myProject"。这样,如果您更改了您的名字或项目名称,它将准确地反映出来。


5
好主意。如果你使用的是Swift,那么应该使用非可选项:NSBundle.mainBundle().bundleIdentifier!(前提是你知道包标识符已经设置,我猜这很可能是实际情况)。 - Juul
为什么您想要在错误域中反映项目名称的更改? - zrslv
1
@zrxq 确实拥有不同的错误域值得重视,但是想象一下,如果您拼错了项目名称或者更改了名称并希望在所有地方都反映出来,最好动态设置而不是硬编码。 - Connor
1
@vare 那一点很清楚,但我不太明白这会提供什么实际的好处。我的理解是这些标识符只需要在应用程序的上下文中是唯一的,就可以了。好吧,也许你只是想让它们更美观,我懂了! - zrslv
1
是的,你提出了一个很好的观点。有时候你想要域名是唯一的,我会假设...例如,如果你正在创建一个SDK或(cocoa)Pod,你希望你的错误域反映它来自哪里,而不是项目的名称。编辑:我还想指出,在这种情况下@"com.myName.myProject"与bundleIdentifier是相同的,这是人们可能不知道的。 - Connor

5
如何创建自定义NSError:
首先,创建一个错误信息的字典。
NSDictionary *userInfo = @{   
   NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil)
                                               };
NSError *error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] 
  code:-58 userInfo:userInfo];

然后将userInfo分配给NSDictionary,就完成了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接