Reputation: 1968
When my custom initializer fails, I am supposed to return nil. What is the convention for cleaning up any memory I've allocated in my initializer, that I was expecting would be cleaned up in dealloc?
Here is a contrived example:
- (id)init
{
if ((self = [super init])) {
instanceVar1 = [[NSString alloc] initWithString:@"blah"];
if (bad_thing_oh_noes) {
return nil;
}
}
return self;
}
- (void)dealloc
{
[instanceVar1 release];
[super dealloc];
}
A more realistic circumstance where I can't efficiently check every error condition before I do allocations would be deserializing a complex object containing arrays and the like.
Anyway, do I clean up the allocated memory before returning nil, do I send a dealloc message to self before returning nil, or is all of this managed for me magically?
Upvotes: 3
Views: 269
Reputation: 28572
If an error occurs during an initializer, you should call release
on self
and return nil
.
if (bad_thing_oh_noes) {
[self release];
return nil;
}
Also, you must make sure that it is safe to call dealloc
on a partially initialized object.
You should call release
only at the point of failure. If you get nil
back from the superclass’s initializer, you should not call release
.
Normally, you should not throw an exception upon initialization failure.
An example from Handling Initialization Failure:
- (id)initWithURL:(NSURL *)aURL error:(NSError **)errorPtr {
self = [super init];
if (self) {
NSData *data = [[NSData alloc] initWithContentsOfURL:aURL
options:NSUncachedRead error:errorPtr];
if (data == nil) {
// In this case the error object is created in the NSData initializer
[self release];
return nil;
}
// implementation continues...
Upvotes: 2