Exceptions and Errors
Until recently, exceptions in Objective-C were implemented using the C setjmp() and longjmp() functions. These have a number of disadvantages. It is expensive to call setjmp(), which saves every register, before you try doing something that may cause exceptions. There is also no support in these functions for running cleanup code between the throw and catch parts of the exception.
Newer implementations use the same “zero-cost” exception model as C++ on GNU platforms. This stores unwinding information in DWARF metadata. It doesn't cost anything to enter a @try block in this scheme, but throwing exceptions is very expensive. You need at least two function calls, and often around a dozen, for every stack frame between where the exception is thrown and where it is caught.
In Java, exceptions are usually implemented by a second return value in the function so they are quite cheap. The VM will also recompile code that contains exceptions to provide a more efficient set of code paths.
As such, although the exception syntax for Objective-C and Java is almost identical, you should try to avoid throwing exceptions in Objective-C. It is fine to use them for truly exceptional behavior, but throwing them often can quickly become a bottleneck in your code.
The most common alternative in recent code is to pass a pointer to a pointer to an NSError object in as an extra argument to methods that are likely to fail. This is then used to return a pointer to an NSError instance if a problem arose.