tags:

views:

30

answers:

2

Say I have the following class:

@interface Frob : NSObject {
    NSData *data;
}
- (id)initWithData:(NSData *)inData;
@end

@implementation Frob
- (id)initWithData:(NSData *)inData 
{
   if ((self = [super init])) {
       data = [inData retain];
   }
   return self;
}
- (void)dealloc
{
    [data release];
    [super dealloc];
}
@end

I now want to add a convenience method to read from a URL. So I write something that looks like this:

- (id)initWithContentsOfURL:(NSURL *)url
{
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:URL options:0 error:&error];
    if (!data) {
        NSLog(@"Frob couldn't read data, error: %@", error);
        [self autorelease]; // !!!
        return nil;
    }
    return [self initWithData:data];
}

That !!! line raised a red flag for me: I'm (effectively) invoking -release on an object that has been +alloc'd but the superclass's -init is never actually called. Is this safe?

Another way to ask the same question: Conceptually, is -release the opposite of +alloc? Or of +alloc and -[<root class> init]?

Clarification would be very much appreciated.

+1  A: 

That's perfectly ok, since there will be no handle to your object after you return nil. If anything you should do a release instead of an autorelease. You're mostly covered by the fact that [nil release] is a no-op, since the superclass hasn't been initialized, nothing in it will be non-nil.

cobbal
+2  A: 

Another way to ask the same question: Conceptually, is -release the opposite of +alloc? Or of +alloc and -[ init]?

No it's not conceptually the opposite. However, conceptually, alloc does a retain which is the opposite of release and your release when initialisation fails undoes that retain.

Note that as a result of the release in your init, dealloc will be called, so dealloc needs to work with a partially (or not at all) initialised object. In your case, your instance variables will all be nil/NULL/0/false when dealloc is called.

JeremyP
Ah, yes, good point about the implicit retain in alloc.
Colin Barrett
"so dealloc needs to work with a partially (or not at all) initialised object" This is my main question, really -- does it?
Colin Barrett
@Colin Barrett: yes it does. However, it's not as bad as you think. All the Objective-C object ivars that are not initialised will be nil and it's perfectly safe to send release to nil.
JeremyP