Exceptions in Objective-C are used mainly for cases of obvious programmer error, such as attempting to access an element outside the bounds of an NSArray
. In contrast, some programming languages use exceptions to specify any sort of recoverable error such as "file not found", but in Objective-C and Cocoa, an NSException
that has been thrown with @throw
typically means there is nothing that can be done to recover.
In either case, the analogy is that exceptions are "thrown" to the catcher, no matter how many function calls sit between the thrower and the catcher. This is in contrast to functions that return error statuses through return values or output parameters. Functions that return error statuses need to ensure that all other functions in the chain return the same error status in order for the original caller at the other end to know there was an error. Exceptions that are thrown bypass all intermediate functions and give the error straight to where it is wanted, the original call-site.
void function3()
{
@throw [NSException exceptionWithName:@"Test" reason:@"Test" userInfo:nil];
}
void function2()
{
function3();
}
void function1()
{
function2();
}
int main()
{
@try
{
function1();
}
@catch(NSException *ex)
{
// handle exception that occurred 3 functions deep
}
}
In general, you should avoid throwing exceptions in Objective-C as a general means of catching recoverable errors because of the way memory management works. In the above, if any objects were allocated in function1
, function2
or function3
but were not autoreleased, then the memory for these objects would be leaked. ARC with "full exception safety" enabled is capable of detecting these cases and handling them appropriately but this only applies for objects in your own code, not any memory allocated by external libraries that you could be using. There is the general expectation that your application will not recover from an exception thrown with @throw
.
See more details in this Q&A.