views:

321

answers:

1

Im newish to objective-c and am starting to wonder what is the common/standard/proper way for handling and catching errors?

It seems like it might be possible to use NSError to do this, is that a good idea or a hijack of cocoa?

+13  A: 

I'm pretty sure that's what the NSError class is there to do - give details about errors. The most common pattern you'll see is a method that takes a pointer to an NSError object, as in:

- (id)doSomethingWithArgument:(id)arg error:(NSError **)error

The method returns some value (or possibly nil) for the result of doing something, but if the call failed will place an NSError object at the pointer passed with details about the failure. Your documentation is responsible for specifying what gets returned if the method does encounter an error.

The other method that comes to mind is the @throw-@catch block; however, in Objective-C @throwing an exception can be rather computationally expensive, and it's usually only recommended to do so in truly exceptional situations.

Edit: wow, turns out a lot of people have really strong opinions about @throwing exceptions. To sum up the (quite helpful) commentary on the issue:

  • Throwing exceptions should most often deal with programmer error (situations that should never happen, and the like); exceptions should not be used for ordinary error handling. Instead, use the error method demonstrated above or post instances of NSNotification.
  • If you do wind up making extensive use of @throw/@catch blocks, be very careful about the logic surrounding them. Objective-C provides a lot of ways to detach methods to run in other threads, or delay execution, etc. Be very careful to account for all those possibilities when you write your code.

Finally, another very valid point:

  • If you do use the error object passed to a method, the return value should indicate it. Don't try to do both (return a partially valid object and set the error object).
Tim
Trying to @throw something that will be caught outside of your scope also has lots of subtle logic issues in ObjC. What if you are called by an NSTimer for instance? Who is going to catch the exception (and avoid crashing)? ObjC exceptions just aren't powerful enough to handle common ObjC idioms. They're generally only useful for dealing with programming errors. NSError is definitely the right way to go if you need a rich error object for general use.
Rob Napier
To clarify, "truly exceptional situations" in Cocoa are almost always caused programmer error, and are usually unrecoverable, or at least easily avoidable with the proper and necessary checks. Throwing an exception just to signal something to the programmer is not a good practice in Objective-C, and nowadays it is even discouraged in Java, not because of the computational cost but because it greatly increases the complexity of the client code.
Quinn Taylor
Continuing this concept, even the idea of centralized error handling has better implementations than exceptions in Cocoa. I often throw error in NSNotifications that are observed by some central error handling object to provide user feedback. When coupled with NSError's encapsulation of retry logic, this can make "post a notification and return" a very effective solution for user-impacting errors.
Rob Napier
Don't use exceptions for anything but fatal errors. Not ever. The return value must definitively indicate error or not. Do not ever touch the `error` parameter *unless* the return value indicates an error.
bbum