views:

107

answers:

2

I've read in many places that you should always initialize Objective-C objects like so:

- (id) init {
    if (self = [super init]) {
        ....
    }
    return self;
}

Because the super's init method may return a separate object from the current self.

Now I'm trying to do something like this, and I'm not sure if I have it right, vis-a-vis how retaining and releasing should work:

- (id) init:(int)idx {
    id obj = [Cache findSelf:idx];
    if (obj) {
        [self release];
        self = [obj retain];
    } else {
        self = [self doLoad];
    }
    return self;
}

I'm mostly curious if this is the correct way to do the retaining and releasing of self and obj. Is there a better way?

+4  A: 

You're correct about the self = [super init] part, since some Cocoa classes actually do return a different object than the one that was allocated. However, this is the exception rather than the rule, and doing so in your own code should be exceedingly rare or not done at all. Although it may be tempting to intercept -init calls, you'd be going against the grain of established convention and what Objective-C programmers expect the code to do.

This type of -init method is generally a bad approach, since -init methods should be as straightforward as possible, and should really be concerned with initializing the object. I'd probably write a convenience method like this:

+ (id) instanceForIndex:(NSUInteger)index {
    id obj = [Cache findSelf:index];
    if (obj == nil) {
      obj = [[self alloc] init];
      // Add to cache
    }
    return [[object retain] autorelease];
}

Then call this method instead of -init. This will make the -init logic much cleaner.

Also, I'm not sure what your Cache class does, but it could be worth rethinking that implementation, and using a hidden static variable to store instances (for example, an NSMutableDictionary, where the key is an NSNumber created from the index). This SO question may be of use.

Quinn Taylor
As a matter of fact, my cache IS a static variable, but it's not quite as simple as seen here; the object itself is an abstract class, and multiple items can have the same index, so really I'm passing in the object itself which compares both the index and the class type to find the right object. There is a separate list for each subclass
Ed Marty
A: 

I agree with Quinn that you should use a convenience class method. Still, I think that your init method is mostly correct, except in your else clause you need to call the parent initializer, i.e. self = [super init].

Daniel Dickison