2011-02-15 124 views
78

在Cocoa中,我应该何时使用NSAssert,NSException,NSError?Objective-C:声明与异常与错误

这就是我一直在想:

NSAssert - 当创建用于程序员自己的利益来仔细检查规则,惯例,假设或前提条件和后置条件的任何客户端程序?

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

NSError - 当与外部系统连接以获取不保证给我结果的文件,数据库或Web服务等数据时?

回答

98

NSAssert将失败时会引发异常。因此,NSAssert可以简单易用地编写代码并检查您在代码中所做的任何假设。这不是(在我看来)是例外的替代方案,只是一种捷径。如果一个断言失败了,那么代码中的某些事情就会发生严重错误,程序不应该继续。

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

你会@throw自己NSException的时间是指当你肯定希望它在发布版本,并在东西像公共图书馆/接口时,一些参数是无效的,或者你已经被称为不正确。请注意,@catch例外并不是真正的标准做法,并且继续运行您的应用程序。如果您尝试使用Apple的某些标准库(例如Core Data),可能会发生不良事情。与断言类似,如果抛出异常,应用程序通常应该相当快地终止,因为这意味着某处存在编程错误。

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

1

一般而言,异常用于表示程序员错误 - 它们是不应该发生的事情。错误用于表示程序正常运行时可能出现的错误情况 - 基本上是用户错误,或者需要是真的但可能不是的外部情况。所以试图删除文档中的某个锁定元素可能是一个错误,并且试图在没有Internet连接的情况下下载文件将是一个错误,但尝试访问集合中的无效元素将是一个例外。

断言通常用于测试,并且AFAIK不会像其他错误处理机制一样用作通用错误处理机制。

+0

断言可以用来执行不变量。例如,`NSParameterAssert(someParam!= nil);`将强制指定参数不能为零的不变量。 – 2011-02-15 21:29:20

+0

@Kevin Ballard:断言通常是由发布版本定义的,或者至少它们是我最后一次检查的,所以就像我说的那样,它们不是一般的错误处理机制。 – Chuck 2011-02-15 22:32:04

3

Cocoa中的约定是,异常表示程序员错误。很多代码,包括框架代码,都不能在抛出异常后正常工作。

任何应该可恢复的错误都由NSError表示。还有一个向用户呈现NSError的系统。正如你所说,这对于易出故障的外部资源是非常有用的。

从概念上讲,断言是给定谓词总是评估为真的陈述;如果没有,该程序被破坏。虽然其行为可以修改,但NSAssert系列默认是一种方便的方式来投掷NSInternalInconsistencyException(可以在发布版本中将其关闭)。

2

编辑: 在Xcode中4.2,assertions are turned off by default for release builds,

现在NSAssert不会被编译成一个释放你的代码构建,但你可以在构建设置更改


@Mike韦勒,你的答案有一个错误。

有一点要注意的是,NSAssert不会被编译成一个发布版本你的代码,所以这通常用于开发过程中健全检查。

其实,NSAssert会被编译成代码如果你没有在你的预编译前缀文件添加NS_BLOCK_ASSERTIONS

在技术说明TN2190我们可以发现:

宏像NDEBUG转关C断言或NS_BLOCK_ASSERTIONS关闭基金会的NSAssert是很重要的指定预编译前缀文件

或者你可以读取这一个:How to know if NSAssert is disabled in release builds?