Exceptions in Objective-C

Exceptions

We in the Objective-C community have a lot of habits that get considered ‘good practice’ simply because someone at sometime told us something was good or bad without explaining why and for some unknown reason we took this knowledge an ran with it until it became canalized. A perfect example of this is exceptions.

Background on rant

I was reviewing some crash logs and found some low hanging fruit I thought I’d tackle. The error was a nil insertion issue, simple enough to fix. The piece of code looked like this.

NSString *bodyText = pendingSharingItem.title;
NSArray *activityItems;

if (pendingSharingItem.linkURLString)
{
    activityItems = @[bodyText, [NSURL URLWithString:pendingSharingItem.linkURLString]];
}
else
{
    activityItems = @[bodyText];
}

The biggest issue here is that were checking for the presence of one thing and inserting another. This is silly behaviour and should be avoided; but it was an understandable mistake given that the pendingSharingItem.linkURLString in this case is initialized with a valid URL and locally is only ever assigned valid URL constants. But what if pendingSharingItem.linkURLString is being manipulated somewhere else, through a dangling pointer perhaps? There are a number of ways to fix this, on of which is a @try-catch block.

Enter the neck beard

“No one who writes Objective-C uses exceptions”1 this or something similar is a common refrain in the community and for a long time it was a totally valid statement as exceptions are implemented using setjmp & longjmp and originally the runtime handled this slowly and offered little support for performing cleanup afterwards. This meant people coming from other languages where exception handling was used for recovery and flow control were in for a really bad time.

Trimming the beard

I racked my brain from where I got this idea that exceptions were bad. When the “exceptions are bad” mentality took root in my skull I had no knowledge of the technical reasons above. Also The issue mentioned above was largely addressed in GCC 3.32 and has only improved since.

The runtime uses exceptions, clearly there are cases where it is prudent to catch them. Apple says array bound issues and such are a good reason to handle exceptions. Also if handling exceptions will not affect your user by putting the app into a bad state then not crashing is probably a good choice.

The Objective-C Phrasebook has an excellent treatment on exceptions and mentions that on 64 bit systems, entering a try/catch block is dirt cheap and throwing is expensive but safe3

Takeaway

So, am I going to start using exceptions? Yes and No. I know the 64 bit system thing applies to OS X so I’ll be catching exceptions there. However, I don’t know that the performance improvements are present on the iPhone and performance is still a concern and while slower devices like the iPhone 4 are still around so I’ll just check each item before inserting it for the time being. I do know I’ll feel sillier the next time I hesitate to catch one though.


  1. If this were true how’d I encounter this issue in the firstplace? 

  2. I can think of 3 or 4 people I know that might have been hacking in Objective-C at that time, where most of you dear readers probably started sometime after 2006 ;) 

  3. Until now I’ve been careful to mention catching exceptions only . Personally I think throwing exceptions as a method of control flow is overused and unless you are writing a framework for others to use you have no business throwing them; check out NSError instead.