preface
In the previous article (which took you through the basics of Load) we explored the load call mechanism. In this article, we will explore the initialize call mechanism and compare the similarities and differences. +initialize is usually used to initialize constants, but the difference between +load and +initialize is often asked in interviews.
Initialize call rule
+initialize
Methods are called before the class or its subclasses receive the first message, which includes instance method and class method calls. That is to say,+initialize
Methods are called lazy-loaded, and if the program never sends a message to a class or its subclasses, that class’s+initialize
Methods are never called.- When subclasses are not implemented
+initialize
Or subclasses in+initialize
Is explicitly called[super initialize]
So superclass+initialize
Methods are called multiple times. - In classification implementation
+initialize
, will only perform classification+initialize
- Of the class
+initialize
Methods in all parent classes+initialize
Called after a method call
Validate invocation rules
This time I will debug the code directly in objC source code and create a new target in the source code I provided, as shown below
Next create the Person class, implement the Load and Initialize methods, and compile and run the target we just created
Load (); initialize (); load ()
For the first few conclusions of this article, I can simply use the code to verify again, I will not go to verify one by one here, directly to explore the source code.
explore
I printed self in load and found that initialize was called, so look at initialize at the breakpoint
This is where you enter the message lookup process of the Runtime, which goes directly to step 3, where you determine if the class has been initialized and initialize it if it has not. So here you can verify conclusion 1 at the beginning, which is called after receiving the first message of the class.
Take a look at the _class_initialize function
void_class_initialize(Class cls) { assert(! cls->isMetaClass()); Class supercls;bool reallyInitialize = NO;
// Make sure super is done initializing BEFORE beginning to initialize cls.
// See note about deadlock above.
supercls = cls->superclass;
if(supercls && ! supercls->isInitialized()) { _class_initialize(supercls); }// Try to atomically set CLS_INITIALIZING.
{
monitor_locker_t lock(classInitLock);
if(! cls->isInitialized() && ! cls->isInitializing()) { cls->setInitializing(); reallyInitialize = YES; }}// Other code omitted
callInitialize(cls);
Copy the code
-
Here is an identifier reallyInitialize, set this to true in CLS ->setInitializing()(RW_INITIALIZING for class ISA)
-
_class_initialize = _class_initialize = _class_initialize = _class_initialize = _class_initialize = _class_initialize = _class_initialize = _class_initialize This is the same method that we used to recursively call the parent class load when we explored load. So here we can verify the conclusion from the beginning: the class’s +initialize method is called after all the parent class’s +initialize method calls.
void callInitialize(Class cls)
{((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);
asm("");
}
Copy the code
- At the end of the call
callInitialize
, using send messagesobjc_msgSend
The way to+initialize
Method is called. That is to say,+initialize
Method call and ordinary method call is the same, go through the process of sending messages. In other words, if the subclass is not implemented+initialize
Method, then the implementation inheriting from the parent class is called; So conclusion three:If the classification of a class is implemented+initialize
Method, then the implementation in this class is overridden. - Therefore, this validates the conclusion above: if a subclass does not implement the +initialize method, the implementation of the parent class will be executed multiple times.