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.
If a designated initializer were to call a secondary initializer in its own class, then it wouldn't be serving the role of designated initializer. The point of the designated initializer is so a subclass implementer knows the single initializer s/he can override that all other initializers will funnel through.
If a designated initializer in a subclass were to call a non-designated initializer in its superclass, then the superclass initializer would likely turn around and call another of the initializers. Due to the dynamic nature of method dispatch, it can't restrict that to calling only the methods implemented at its level. That call is very likely to be to one of the subclass's overrides, which would funnel into the subclass's designated initializer, resulting in infinite recursion.
Let's consider
NSSet
. It has a designated initializer:It also has some secondary initializers, like this one:
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:What happens when you do this:
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.