Returning nil from init

13 Aug

I was recently asked why we should bother checking for nil in the code below? Shouldn’t init always return an object?

NSMutableArray *buttons = [[NSMutableArray alloc] init];
LMActivityButton *activityButton = [[LMActivityButton alloc] init];
if (activityButton != nil) {
    [buttons addObject:activityButton];
}

Nope. It’s actually perfectly valid to return nil from an initializer. In fact, if initialization fails it should return nil. It’s the preferred way to indicate initialization failed.

You’ve been (hopefully) partially adhering to this convention without even thinking about it. Every time you type the following bit:

SomeClass *someObject = [[SomeClass alloc] init];

Instead of

SomeClass *someObject = [SomeClass alloc];
[someObject init];

The second version is unsafe, because init could return nil and release its memory (or substitute an entirely different object).

Now, we could look at the source for LMActivityButton above and see that it doesn’t actually implement an initialization method; it defaults to NSObject’s init. Knowing that NSObject doesn’t actually do anything in init, it just returns self, one could argue the check for nil is unneeded. And today, one would be correct. However, nothing says that LMActivityButton won’t add its own custom initializer in the future, and that said initializer won’t return nil to indicate failure – though admittedly it would be highly unlikely / unexpected for a button to do something so complex as to fail initialization.

For me, this really comes down to good habits. It’s a good habit to check for nil from an initializer if you’re going to be doing work that expects it to be non-nil, like adding it to an array. It also serves to remind you, and others, that init can fail, and that other, more critical, places in your code should protect against it.