Assuming our -init
method only invokes messages on self
, why is it common to check if self != nil
if messaging nil
has no effect?
Let's say we have an initializer as follows:
- (id)init
{
self = [super init];
if (self) {
[self doThis];
[self setFoo:@"Bar"];
}
return self;
}
Instead of checking self
, we could write:
- (id)init
{
self = [super init];
[self doThis];
[self setFoo:@"Bar"];
return self;
}
Now if for some reason [super init]
returns nil
, there would be no difference in the outcome of the method as far as I know. Why then do we constantly perform this check?
You can send a message to nil, but you cannot access the instance variables of nil. You'll get an EXC_BAD_ACCESS
exception.
Consider a class that has instance variables:
@implementation MyObject {
int instanceVariable;
}
- (id)init {
self = [super init];
instanceVariable = 7;
return self;
}
What happens if [super init]
returns nil in this example? You will try to access that instanceVariable
off of a null pointer and you will get an exception.
Even if you're not accessing any instance variables, other things can certainly go wrong if you don't check for self == nil
. You can easily leak malloc
-allocated memory or file handles, or pass yourself to some method that's not expecting nil.
Other answers claim that you can leak objects if you don't check for nil. For example:
@implementation MyObject
@synthesize someProperty; // assume it's an NSObject *
- (id)init {
self = [super init];
[self setSomeProperty:[[NSObject alloc] init]];
return self;
}
This won't leak under ARC, even if self
is nil. Under manual reference counting (MRC), this example will leak whether self
is nil or not, because there's nothing to balance the +1 retain count from [NSObject alloc]
.
The proper way to do it under MRC is this:
- (id)init {
self = [super init];
[self setSomeProperty:[[[NSObject alloc] init] autorelease]];
}
or this:
- (id)init {
self = [super init];
NSObject *object = [[NSObject alloc] init];
[self setSomeProperty:object];
[object release];
return self;
}
Neither of those will leak, whether self
is nil or not.
If you bypass the setter method, like this, you'll just crash if self
is nil:
- (id)init {
self = [super init];
_someProperty = [[NSObject alloc] init];
return self;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With