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.
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.