views:

62

answers:

1

I have three Objective-C classes:

@interface ClassA : NSObject{
     IBOutlet id<ClassAProtocol>delegate
     //other instance variables
}

//methods
@end

@interface ClassB : ClassA{
     //instance variables
}

//methods
@end

@interface ClassC : ClassA{
     //instance variables
}

//methods
@end

My objective is so that when an instance of ClassA is called for in either code or InterfaceBuilder, an instance of ClassB or ClassC is actually created. Whether it will be ClassB or ClassC depends on a return value of a method in ClassAProtocol as implemented by the delegate object.

@implementation ClassA

static BOOL _initFromSubclass = NO;

-(id)init{
     if(_initFromSubclass){
          _initFromSubclass = NO;
          self = [super init];
     }else {
          _initFromSubclass = YES;
          if([delegate shouldInitClassB]){
                self = [[ClassB alloc] init];
          }else{
                self = [[ClassC alloc] init];
          }
     }

     return self;
}

//other methods
@end

This doesn't work the way I wanted because at the init call, the delegate (set in Interface Builder) is still nil, and so the object created is always ClassC. Also, a ClassA object is created first, then, in its init call, creates a new ClassC object, with a different memory address, and no ClassA object is dealloced. I have three questions:

1)What happens to the original ClassA object? (I think it's leaked, but I want to know).

2)How do I avoid the leak?

3)How do I accomplish what I actually want? By the time the delegate is set (say, in awakeFromNib method), it's too late to reset the object.

+3  A: 
  1. Yes I think it will be leaked because it has a retain count of +1 after the alloc but nothing will release it.

  2. You can use [self release] before reassigning the value of self. Some argue that it should be [self dealloc] directly, but I personally prefer the former.

  3. Objects instantiated from nibs are sent initWithCoder: messages I think, so override that instead of init. Although, at this point, I'm still not sure whether delegate will be set.

dreamlax
Are you sure about that 3rd one? For `initWithCoder:` to work, the class needs to implement the `NSCoding` protocol, which NSObject by default does not, and neither do my classes, but I have no problem creating instances of any of them in InterfaceBuilder. Also, when I create `ClassA` in IB, it goes through that init call I posted above twice -- first as itself, then as a call to `[super init]` from `ClassC`.
executor21