Objective-C:断言、异常和错误

时间:2022-09-07 07:34:48

In Cocoa, when should I use NSAssert, NSException, NSError?

在Cocoa中,我什么时候应该使用NSAssert NSException, NSError?

Here's what I've been thinking:

我一直在想:

NSAssert - When creating any client program used for the programmers own benefit to double check rules, conventions, assumptions, or pre-conditions and post-conditions?

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

NSException - When creating a third-party library for the benefit of other programmers that use the library, so that they immediately know when an input is invalid?

NSException—为使用该库的其他程序员创建第三方库时,以便他们立即知道输入是无效的?

NSError - When interfacing with an external system to get data like a file, database, or web service that isn't guaranteed to give me a result?

NSError -当与外部系统交互以获取文件、数据库或web服务等数据时,是否保证不会给我结果?

4 个解决方案

#1


98  

An NSAssert will throw an exception when it fails. So NSAssert is there to be short and easy way to write and to check any assumptions you have made in your code. It is not (in my opinion) an alternative to exceptions, just a shortcut. If an assertion fails then something has gone terribly wrong in your code and the program should not continue.

NSAssert失败时会抛出异常。NSAssert是一种很简单,很容易写的方法来检查你在代码中做的任何假设。在我看来,这不是一个例外,只是一个捷径。如果断言失败,那么代码中出现了严重错误,程序就不能继续了。

One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development. I actually tend to use a custom assert macro that is always active.

需要注意的一点是,NSAssert不会在发布构建中编译到您的代码中,因此这通常用于开发期间的完整性检查。实际上,我倾向于使用自定义的assert宏,它始终是活动的。

The times you would @throw your own NSException are when you definitely want it in a release build, and in things like public libraries/interface when some arguments are invalid or you have been called incorrectly. Note that it isn't really standard practice to @catch an exception and continue running your application. If you try this with some of Apple's standard libraries (for example Core Data) bad things can happen. Similar to an assert, if an exception is thrown the app should generally terminate fairly quickly because it means there is a programming error somewhere.

在发布版本中,当你想要发布自己的NSException时,你会使用@throw,而当某些参数无效或者你被错误地调用时,在公共库/接口之类的东西中。注意,@catch异常并继续运行应用程序并不是真正的标准实践。如果您尝试使用苹果的一些标准库(例如Core Data),就会发生糟糕的事情。与断言类似,如果抛出异常,应用程序通常应该很快终止,因为这意味着某个地方存在编程错误。

NSErrors should be used in your libraries/interfaces for errors that are not programming errors, and that can be recovered from. You can provide information/error codes to the caller and they can handle the error cleanly, alert the user if appropriate, and continue execution. This would typically be for things like a File-not-found error or some other non-fatal error.

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

#2


3  

The convention in Cocoa is that an exception indicates a programmer error. A lot of code, including framework code, is not designed to work properly after an exception is thrown.

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

Any sort of error that should be recoverable is represented by an NSError. There’s also a system for presenting NSErrors to the user. As you say, this is mostly useful for fallible external resources.

任何应该可恢复的错误都由NSError表示。还有一个向用户显示NSErrors的系统。正如您所言,这对于容易出错的外部资源非常有用。

Conceptually, an assertion is a statement that a given predicate always evaluates to true; if it doesn’t, the program is broken. While its behaviour can be modified, the NSAssert family is by default a convenient way of throwing NSInternalInconsistencyExceptions (with the option of turning them off in release builds).

从概念上讲,断言是给定谓词总是计算为true的语句;如果没有,程序就会被破坏。虽然可以修改其行为,但默认情况下,NSAssert家族是抛出nsinternalinconsistencyexception的一种方便方式(可以在发行版构建中关闭它们)。

#3


2  

Edit: In Xcode 4.2, assertions are turned off by default for release builds,

编辑:在Xcode 4.2中,默认情况下,断言被关闭,用于发布版本,

Now NSAssert will not be compiled into your code in a release build, but you can change it in build settings

现在NSAssert不会在发布版本中编译到您的代码中,但是您可以在构建设置中更改它。


@Mike Weller, There are one wrong in your answer.

@Mike Weller,你的回答有一个错误。

One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development.

需要注意的一点是,NSAssert不会在发布构建中编译到您的代码中,因此这通常用于开发期间的完整性检查。

Actually, NSAssert will be compiled into your code if you don't add NS_BLOCK_ASSERTIONS in your precompiled prefix files.

实际上,如果不在预编译的前缀文件中添加ns_block_断言,那么NSAssert将被编译到代码中。

In Technical Note TN2190 we can find:

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

Macros like NDEBUG to turn off C assert or NS_BLOCK_ASSERTIONS to turn off Foundation's NSAssert are important to specify for your precompiled prefix files

像NDEBUG这样的宏用于关闭C assert或ns_block_assert以关闭Foundation的NSAssert,对于为预编译的前缀文件指定这些宏非常重要

Or you can read this one:How to know if NSAssert is disabled in release builds?

或者您可以阅读这个:如何知道NSAssert在发布版本构建中是否被禁用?

#4


1  

In general, exceptions are used to signal programmer errors — they're things that shouldn't happen. Errors are used to signal error conditions that might come up in the normal operation of the program — user errors, basically, or external conditions that need to be true but might not be. So trying to delete some locked element in a document might be an error, and trying to download a file without an Internet connection would be an error, but trying to access an invalid element in a collection would be an exception.

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

Assertions are typically used in testing, and AFAIK are not used as a general error-handling mechanism like the others.

断言通常用于测试,而AFAIK不被用作一般的错误处理机制。

#1


98  

An NSAssert will throw an exception when it fails. So NSAssert is there to be short and easy way to write and to check any assumptions you have made in your code. It is not (in my opinion) an alternative to exceptions, just a shortcut. If an assertion fails then something has gone terribly wrong in your code and the program should not continue.

NSAssert失败时会抛出异常。NSAssert是一种很简单,很容易写的方法来检查你在代码中做的任何假设。在我看来,这不是一个例外,只是一个捷径。如果断言失败,那么代码中出现了严重错误,程序就不能继续了。

One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development. I actually tend to use a custom assert macro that is always active.

需要注意的一点是,NSAssert不会在发布构建中编译到您的代码中,因此这通常用于开发期间的完整性检查。实际上,我倾向于使用自定义的assert宏,它始终是活动的。

The times you would @throw your own NSException are when you definitely want it in a release build, and in things like public libraries/interface when some arguments are invalid or you have been called incorrectly. Note that it isn't really standard practice to @catch an exception and continue running your application. If you try this with some of Apple's standard libraries (for example Core Data) bad things can happen. Similar to an assert, if an exception is thrown the app should generally terminate fairly quickly because it means there is a programming error somewhere.

在发布版本中,当你想要发布自己的NSException时,你会使用@throw,而当某些参数无效或者你被错误地调用时,在公共库/接口之类的东西中。注意,@catch异常并继续运行应用程序并不是真正的标准实践。如果您尝试使用苹果的一些标准库(例如Core Data),就会发生糟糕的事情。与断言类似,如果抛出异常,应用程序通常应该很快终止,因为这意味着某个地方存在编程错误。

NSErrors should be used in your libraries/interfaces for errors that are not programming errors, and that can be recovered from. You can provide information/error codes to the caller and they can handle the error cleanly, alert the user if appropriate, and continue execution. This would typically be for things like a File-not-found error or some other non-fatal error.

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

#2


3  

The convention in Cocoa is that an exception indicates a programmer error. A lot of code, including framework code, is not designed to work properly after an exception is thrown.

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

Any sort of error that should be recoverable is represented by an NSError. There’s also a system for presenting NSErrors to the user. As you say, this is mostly useful for fallible external resources.

任何应该可恢复的错误都由NSError表示。还有一个向用户显示NSErrors的系统。正如您所言,这对于容易出错的外部资源非常有用。

Conceptually, an assertion is a statement that a given predicate always evaluates to true; if it doesn’t, the program is broken. While its behaviour can be modified, the NSAssert family is by default a convenient way of throwing NSInternalInconsistencyExceptions (with the option of turning them off in release builds).

从概念上讲,断言是给定谓词总是计算为true的语句;如果没有,程序就会被破坏。虽然可以修改其行为,但默认情况下,NSAssert家族是抛出nsinternalinconsistencyexception的一种方便方式(可以在发行版构建中关闭它们)。

#3


2  

Edit: In Xcode 4.2, assertions are turned off by default for release builds,

编辑:在Xcode 4.2中,默认情况下,断言被关闭,用于发布版本,

Now NSAssert will not be compiled into your code in a release build, but you can change it in build settings

现在NSAssert不会在发布版本中编译到您的代码中,但是您可以在构建设置中更改它。


@Mike Weller, There are one wrong in your answer.

@Mike Weller,你的回答有一个错误。

One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development.

需要注意的一点是,NSAssert不会在发布构建中编译到您的代码中,因此这通常用于开发期间的完整性检查。

Actually, NSAssert will be compiled into your code if you don't add NS_BLOCK_ASSERTIONS in your precompiled prefix files.

实际上,如果不在预编译的前缀文件中添加ns_block_断言,那么NSAssert将被编译到代码中。

In Technical Note TN2190 we can find:

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

Macros like NDEBUG to turn off C assert or NS_BLOCK_ASSERTIONS to turn off Foundation's NSAssert are important to specify for your precompiled prefix files

像NDEBUG这样的宏用于关闭C assert或ns_block_assert以关闭Foundation的NSAssert,对于为预编译的前缀文件指定这些宏非常重要

Or you can read this one:How to know if NSAssert is disabled in release builds?

或者您可以阅读这个:如何知道NSAssert在发布版本构建中是否被禁用?

#4


1  

In general, exceptions are used to signal programmer errors — they're things that shouldn't happen. Errors are used to signal error conditions that might come up in the normal operation of the program — user errors, basically, or external conditions that need to be true but might not be. So trying to delete some locked element in a document might be an error, and trying to download a file without an Internet connection would be an error, but trying to access an invalid element in a collection would be an exception.

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

Assertions are typically used in testing, and AFAIK are not used as a general error-handling mechanism like the others.

断言通常用于测试,而AFAIK不被用作一般的错误处理机制。