I've just been reading up on how to properly fail in an init method and the docs seem to disagree with each other. One recommends throwing an exception while the others recommend cleaning up and returning nil. What's the current best practice here?
The method I've always used is cleaning up and returning nil. The three methods you mention in your question title may cause segfaults higher up in the call hierarchy, whereas returning nil will not. I believe that the Apple docs themselves say to return nil on failure. Where are you finding discrepancies?
I believe that the generally accepted practice is to return nil on failure. But you do want to release self to avoid a leak:
-(id)init
{
if (self = [super init]) {
...
if (thingsWentWrong) {
[self release];
return nil;
}
...
}
return self;
}
Cocoa's philosophy on exceptions is that they should only be thrown in situations that are programmer errors, like passing an illegal argument to a method. If something else goes wrong, the method should just return NO or nil, and hopefully report the details via an NSError** "out" parameter.
This includes -init methods. If the error situation is something that could legitimately occur in the finished product, then the method should release self (to avoid a leak) and return nil.
The correct solutions (exceptions and/or [self release]; return nil;
) having been covered, I'll address the incorrect solutions.
Don't send dealloc
directly. That's release
's job. (And if your code is ever running under GC, dealloc
is inapplicable, and I could only speculate on what problems calling it would cause.)
Double-don't use super
to send it directly. That would skip over your own dealloc
implementation.