According to the documentation, a class's designated initializer in Objective-C must call the designated initializer of its base class.
Another rule is that secondary initializers must call the designated initializer of their own class.
But if the second rule is followed, why can't a designated initializer call a secondary initializer in its base class? This base secondary initializer will ultimately call its own level's D.I., so the object will still be properly initialized, right?
The difference seems to be who chooses defaults for missing variables -- you or your base class.
Let's consider NSSet
. It has a designated initializer:
- (id)initWithObjects:(const id *)objects count:(NSUInteger)cnt {
// initialization code here
return self;
}
It also has some secondary initializers, like this one:
- (id)initWithArray:(NSArray *)array {
NSUInteger count = array.count;
id objects[count];
[array getObjects:objects range:NSMakeRange(0, count)];
return [self initWithObjects:objects count:count];
}
Now you want a subclass of NSSet
that automatically rejects the string "Bob". So you dutifully override the designated initializer in your subclass, but you call one of super's secondary initializers:
@implementation BobRejectingSet
- (id)initWithObjects:(const id *)objects count:(NSUInteger)count {
NSMutableArray *array = [[NSMutableArray alloc] initWithCount:count];
for (NSUInteger i = 0; i < count; ++i) {
if (![objects[i] isEqual:@"Bob"]) {
[array addObject:objects[i]];
}
}
return [super initWithArray:array];
}
What happens when you do this:
BobRejectingSet *noBobs = [[BobRejectingSet alloc] initWithArray:someObjects];
Since you didn't override initWithArray:
, the program calls -[NSSet initWithArray:]
, which calls the designated initializer, initWithObjects:count:
. You overrode the designated initializer, so it calls your method. Your method filters out the Bobs, and then calls super's secondary initializer, initWithArray:
… which turns around and calls your designated initializer override again. Unlimited recursion. Stack overflow. You get the segmentation-violation-core-dumped blues.
That's why you always use super's designated initializer.