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

  1. +initializeMethods are called before the class or its subclasses receive the first message, which includes instance method and class method calls. That is to say,+initializeMethods are called lazy-loaded, and if the program never sends a message to a class or its subclasses, that class’s+initializeMethods are never called.
  2. When subclasses are not implemented+initializeOr subclasses in+initializeIs explicitly called[super initialize]So superclass+initializeMethods are called multiple times.
  3. In classification implementation+initialize, will only perform classification+initialize
  4. Of the class+initializeMethods in all parent classes+initializeCalled 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 callcallInitialize, using send messagesobjc_msgSendThe way to+initializeMethod is called. That is to say,+initializeMethod call and ordinary method call is the same, go through the process of sending messages. In other words, if the subclass is not implemented+initializeMethod, then the implementation inheriting from the parent class is called; So conclusion three:If the classification of a class is implemented+initializeMethod, 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.

conclusion