Objective-C: Assertion vs. Exception vs. Error

Objective CCocoaConventions

Objective C Problem Overview


In Cocoa, when should I use 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?

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?

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?

Objective C Solutions


Solution 1 - Objective C

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.

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.

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.

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.

Solution 2 - Objective C

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.

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.

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).

Solution 3 - Objective C

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

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


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

> 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.

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

In Technical Note TN2190 we can find: > 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

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

Solution 4 - Objective C

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.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTobiasView Question on Stackoverflow
Solution 1 - Objective CMike WellerView Answer on Stackoverflow
Solution 2 - Objective CJens AytonView Answer on Stackoverflow
Solution 3 - Objective Clikid1412View Answer on Stackoverflow
Solution 4 - Objective CChuckView Answer on Stackoverflow