Objective-C:断言与异常与错误


79

在可可中,何时应使用NSAssert,NSException,NSError?

这是我一直在想的:

NSAssert-创建用于程序员的任何客户端程序时,自己是否有好处来仔细检查规则,约定,假设或前提条件和后置条件?

NSException-当创建第三方库以使使用该库的其他程序员受益时,他们将立即知道何时输入无效?

NSError-当与外部系统接口以获取诸如文件,数据库或Web服务之类的数据时,不能保证能给我带来结果吗?

Answers:


103

一个NSAssert失败时会抛出异常。因此,NSAssert提供了一种简便的方法来编写和检查您在代码中所做的任何假设。(在我看来)它不是例外的替代品,只是捷径。如果断言失败,则说明您的代码出现了严重错误,程序不应继续执行。

需要注意的一件事是,NSAssert不会在发行版本中编译到您的代码中,因此通常在开发过程中用于完整性检查。实际上,我倾向于使用始终处于活动状态的自定义断言宏。

您将@throw拥有自己的NSException的时候是您肯定要在发行版本中以及在某些参数无效或被错误调用的公共库/接口之类的情况中使用它。请注意,@catch例外情况并继续运行应用程序并不是真正的标准做法。如果您使用Apple的某些标准库(例如Core Data)尝试此操作,则可能会发生不良情况。与断言类似,如果引发异常,则应用程序通常应很快终止,因为这意味着某个地方存在编程错误。

NSErrors应该在您的库/接口中用于不是编程错误且可以从中恢复的错误。您可以向调用者提供信息/错误代码,它们可以干净地处理错误,在适当时警告用户并继续执行。这通常适用于诸如文件未找到错误或其他一些非致命错误。


15
明确地说,不应使用NSException表示可恢复的错误。
bbum 2011年

28
换句话说:Obj-C的NSException == Java的Error类,而Obj-C的NSError == Java的Exception类。祝您一致!
Tustin2121'1

2
实际上,如果您未在预编译的前缀文件中添加NS_BLOCK_ASSERTIONS,则NSAssert将被编译为您的代码。阅读下面的答案(立即获得50个
荣誉

3

Cocoa中的约定是异常表示程序员错误。引发异常后,很多代码(包括框架代码)都无法正常工作。

应该恢复的任何类型的错误都由 NSError。还有一个向NSError用户展示的系统。如您所说,这对于容易出错的外部资源很有用。

从概念上讲,断言是给定谓词始终评估为true的声明;如果没有,则程序已损坏。尽管可以修改其行为,但NSAssert默认情况下,该系列是抛出NSInternalInconsistencyExceptions的便捷方法(可以选择在发行版本中将其关闭)。


2

编辑:在Xcode 4.2中,默认情况下,对于发布版本,断言处于关闭状态,

现在,NSAssert不会在发行版本中编译到您的代码中,但是您可以在版本设置中对其进行更改


@迈克·韦勒,您的回答有误。

需要注意的一件事是,NSAssert不会在发行版本中编译到您的代码中,因此通常在开发过程中用于完整性检查。

实际上,如果不添加预编译的前缀文件,NSAssert将被编译到您的代码NS_BLOCK_ASSERTIONS中。

在技​​术说明TN2190中,我们可以找到:

为预编译的前缀文件指定重要的宏,如NDEBUG可以关闭C断言或NS_BLOCK_ASSERTIONS可以关闭Foundation的NSAssert。

或者您可以阅读以下内容:如何知道发行版本中是否禁用了NSAssert?


1

通常,异常用于指示程序员错误-它们是不应该发生的事情。错误用于表示可能在程序正常运行中出现的错误情况-基本是用户错误,或者是必须为真但可能不是的外部条件。因此,尝试删除文档中的某些锁定元素可能是一个错误,而尝试在没有Internet连接的情况下下载文件将是一个错误,但是尝试访问集合中的无效元素将是一个例外。

断言通常用于测试中,而AFAIK不像其他方法那样用作一般的错误处理机制。


断言可用于强制不变式。例如,NSParameterAssert(someParam != nil);将强制不变,即指定的参数不能为nil。
莉莉·巴拉德

@Kevin Ballard:断言通常是在发行版本之外定义的,或者至少是我最后一次检查过的,因此就像我说的那样,它们不是通用的错误处理机制。
Chuck

1
它们可以,但是默认情况下不会被省略。您必须更改构建设置才能获得该行为。
莉莉·巴拉德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.