For iOS developers,+load().+initialize().-init()Methods should be familiar, but for these methods call logic and order, may occasionally have doubts, this article through the way of demo, to explore these methods

+ load()

The +load() method is called when a class or class is added to the Objective-C Runtime. Implementing this method allows us to perform some class-related behavior when the class is loaded. A subclass’s +load method is executed after all its parent’s +load() methods, The class’s +load() method is executed after its main class’s +load() method. But the order in which the +load() methods are called between different classes is uncertain

TestClass
TestClassSubClass
TestClass
TestClass+Z
TestClass+Y
+load()
main()

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        NSLog(@" %s", __func__);
        
        returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); }}Copy the code

As we can see, the +load() function is called before main() and is only called once during the entire APP run. The +load() method is called directly using the memory address of the function (CLS, SEL_load); Instead of sending objc_msgSend, the parent TestClass’s +load() method is called first, followed by subclasses and classes. The order of +load() calls for multiple classes depends on the order in which they are compiled. We will change the Compile order of the classification in Bulid Phases->Compile Sources

TestClass+Z
+load()
TestClass+Y

Conclusion:
  • +load()Method is called in themain()Function, and it doesn’t have to be called, the program starts loading all the files, if the files are overwritten+load()Methods, main classes, subclasses, and classes all load calls+load()Methods;
  • The loading sequence of main class and classification is as follows: main class takes precedence over classification, regardless of compilation sequence;
  • The loading order between categories depends on the order of compilation: compile first, load first, and then load later.
  • Priority order: (Parent > Subclass > category);
  • because+load()Is in themain()Function is called before, so do not do time-consuming or blocking operations in this method, which will affect the startup speed;
  • Do not initialize the object, because inmain()Function is called automatically before,+load()When a method is called, the user cannot be sure that the object to be used has already been loaded, so never initialize the object here;
  • The Method Swizzle operation can be performed in the +load() Method to swap methods based on business requirements.

+ initialize()

The +initialize() method is called before the class or its subclasses receive the first message, which includes instance and class method calls. In other words, the +initialize() method is called lazy-loaded. If the program never sends a message to a class or its subclasses, The class’s +initialize() method will never be called, and we’ll test the call in code as well

  • inTestClassimplementation+ initialize()Method, subclasses, and classes are not implemented, and are called as follows, respectively
      TestClass *class1 = [[TestClass alloc] init];
      TestClass *class2 = [[TestClass alloc] init];
    
//    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
//    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
//    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
//    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
//    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

    TestClass *class1 = [[TestClass alloc] init];
    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code


//    TestClass *class1 = [[TestClass alloc] init];
//    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

TestClass Initialize is called only once, regardless of how many TestClass objects we create. If a TestClassSubClass object is created, whether or not a TestClass object is created, [TestClass initialize] is called twice, so if the subclass does not implement the +initialize() method, the parent +initialize() method will be called.

  • inTestClassAnd subclasses, respectively+ initializemethods
    TestClass *class1 = [[TestClass alloc] init];
    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

//    TestClass *class1 = [[TestClass alloc] init];
//    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

+ initialize()
+ initialize()
+ initialize()
+ initialize()
+ initialize()

  • inTestClassAnd subclasses, classification, respectively+ initialize()methods
    TestClass *class1 = [[TestClass alloc] init];
    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code
//    TestClass *class1 = [[TestClass alloc] init];
//    TestClass *class2 = [[TestClass alloc] init];
    
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

+ initialize()
TestClass+Y
+ initialize()
TestClass+Y
+ initialize()
+ initialize()

Conclusion:
  • Of the parent class+ initialize()Methods are executed before subclasses;
  • When a subclass is not implemented+ initialize()Method, the parent class is called+ initialize()Method, subclass implementation+ initialize()Method overrides the parent class+ initialize()Methods;
  • When there is more than oneCategoryImplement the+ initialize()Method, which overrides the methods in the class and executes only one (executesCompile SourcesLast one on the listCategory+ initialize()Methods).

– init()

  • inTestClassAnd subclasses are implemented separately-init()methods
    TestClassSubClass *subClass1 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass2 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass3 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass4 = [[TestClassSubClass alloc] init];
    TestClassSubClass *subClass5 = [[TestClassSubClass alloc] init];
Copy the code

-init()
-init()

  • Only in theTestClassimplementation-init()methods

    The result of the call is

    We find that the subclass is not implemented-init()Method is called only once for each object initialized-init()methods

Conclusion:
  • +load()+initialize()Is called before instantiating the object, which is called inmain()Function before, the latter is inmain()After the function;
  • +load()+initialize()Methods do not explicitly call the parent class’s methods but are called automatically, even if subclasses do not+initialize()Methods also call methods of their parent class,+load()Method does not call the parent class;
  • +load()+initialize()Methods use locks internally, so they are thread-safe and should be implemented as simply as possible to avoid thread blocking and reusing locks;
  • +load()Methods are commonly used tomethod swizzle.+initialize()Often used to initialize global and static variables.