-init
and +initialize
are completely different things. The first is for initializing instances; the second is for initializing classes.
The first time any given class is messaged, the runtime makes sure to invoke +initialize
on it and its superclasses. The superclasses are initialized first because they need to be ready before any subclass can initialize itself.
So, the first that time YourSubclass
is messaged, the runtime might do something like:
[NSObject initialize];
[YourClass initialize];
[YourSubclass initialize];
(Although it's very unlikely that this would be the first time that NSObject
is messaged, so probably it doesn't need to be initialized at this point. It's just for illustration.)
If YourSubclass
doesn't implement +initialize
, then the [YourSubclass initialize]
invocation shown above will actually call +[YourClass initialize]
. That's just the normal inheritance mechanism at work. That will make the second time that +[YourClass initialize]
has been called.
Since the work done in a +initialize
method is usually the sort of thing that should only be done once, the guard if (self == [TheClassWhoseImplementationThisMethodIsPartOf class])
is necessary. Also, that work often assumes that self
refers to the current class being written, so that's also a reason for the guard.
The second answer you cite notes an exception, which is the old-style mechanism for registering KVO dependent keys with the +setKeys:triggerChangeNotificationsForDependentKey:
method. That method is specific to the actual class it's invoked on, not any subclasses. You should avoid it and use the more modern +keyPathsForValuesAffectingValueForKey:
or +keyPathsForValuesAffecting<Key>
methods. If you must use the old way, put that part outside of the guard. Also, subclasses of such a class must call through to super
which is not normally done.
Update:
A +initialize
method should not normally call through to super
because the runtime has already initialized the superclass. If and only if the superclass is known to register dependent keys using the old mechanism, then any subclasses must call through to super.
The same worry does not exist in the case of -init
because the runtime is not automatically calling the superclass init method for you before calling yours. Indeed, if your init method does not call through to super
, then nothing will have initialized the superclass's "part" of the instance.