Initialize and Load are two methods in NSObject class, which we are familiar with, but we do not have a detailed understanding of. Today, we will take a look at the initialize and load methods based on the official Apple documentation.

initialize

The initialize method is used to initialize a class before it receives its first message.

Initializes the class before it receives its first message.

+ (void)initialize;
Copy the code
  1. The Runtime sends an Initialize message to each class before the application class receives its first message.
  2. Superclasses will receive the Initialize message before Subclasses.
  3. The Initialize method is thread-safe. While initialize is running, the class is locked and no other thread can send messages to the class, so we try to avoid complicated implementation in initialize.

Next we explore the initialize method in code. We have three classes: Man, Woman, and Person. “Man” and “Woman” inherit from “Person”.


#import <Foundation/Foundation.h>

@interface Person : NSObject

@end


#import "Person.h"

@implementation Person+ (void)initialize{
    NSLog(@"call person initialize");
}

@end
Copy the code
#import "Person.h"

@interface Man : Person

@end

#import "Man.h"

@implementation Man

@end

Copy the code

#import "Person.h"

@interface Woman : Person

@end

#import "Woman.h"

@implementation Woman

@end

Copy the code

In main.m the method code is as follows:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];
    }
    return 0;
}
Copy the code

We run the program and get the following output

 call person initialize
Copy the code

Set a breakpoint in the Initialize method of Person and look at the stack call. The first method of the Person call is indeed initialize, which initializes the Person before the Person receives the first message.

Next, modify the main.m code to generate object instances of Person,Man, and Woman.

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];
        Man *m = [[Man alloc] init];
        Woman *w = [[Woman alloc] init];
    }
    return 0;
}
Copy the code

Run the program and view the console output

 call person initialize
 call person initialize
 call person initialize
Copy the code

We can see that if the subclass does not implement initialize, the Runtime will call the parent class’s initialize implementation, so we do not need to call super initialize in the subclass. This means that the parent class’s initialize will be called multiple times. Then we can adopt the following ways to avoid this problem.

+ (void)initialize {
  if (self == [ClassName self]) {
    // ... do the initialization ...}}Copy the code

What if the Person subclasses Man and Woman both implement the initialize method?

@implementation Man+ (void)initialize{
    NSLog(@"call man initialize"); } + (void)initialize{
    NSLog(@"call woman initialize");
}
@end


Copy the code

Run the program and view the console output. You can see that each class is implemented by calling its own initialize method.

call person initialize
call man initialize
call woman initialize
Copy the code

Each class has one and only one initialize method call. If we want to initialize the class and category separately, we should use the Load method.

load

As you can see from the documentation, the load method is called when a class or category is added to the Runtime.

Invoked whenever a class or category is added to the Objective-C runtime; 
implement this method to perform class-specific behavior upon loading.

+ (void)load;
Copy the code
  1. Like initialize, the load of the class will be called after the load of the superlcasses.
  2. The category load method is called after the class load method is called.

Now let’s explore the load method in code, again using the previous example, we have three classes, Man, Woman, and Person. “Man” and “Woman” inherit from “Person”.

The Person class implements the load method


//Person.m
#import "Person.h"

@implementation Person+ (void)initialize{
    NSLog(@"call person initialize"); } + (void)load{
    NSLog(@"call person load");
}

// main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];

    }
    return 0;
}

@end
Copy the code

Run the program and look at the console output to see that the load method is called before the Initialize method.

call person load
call person initialize
Copy the code

Next modify the main.m implementation

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];
        Man *m = [[Man alloc] init];
        Woman *w = [[Woman alloc] init];
    }
    return 0;
}

Copy the code

When you run the program and look at the console output, you can see that the Runtime does not automatically call the parent’s implementation of the load method when the subclass does not implement it

call person load
call person initialize
call man initialize
call woman initialize
Copy the code

Next modify the man.m and woman.m implementations


// Man.m
#import "Man.h"

@implementation Man+ (void)initialize{
    NSLog(@"call man initialize"); } + (void)load{
    NSLog(@"call man load");
}
@end

// Woman.m
#import "Woman.h"

@implementation Woman+ (void)initialize{
    NSLog(@"call woman initialize"); } + (void)load{
    NSLog(@"call woman load");
}

@end
Copy the code

We do not explicitly call the load method of the parent class in Woman or Man, but the load method of the parent class is called before the initialize method. This is the same as the initialize method, because the parent class is initialized first.

call person load
call woman load
call man load
call person initialize
call man initialize
call woman initialize
Copy the code

I’m going to create a new category of Man called Man(Work),

// Mam + Work.m
#import "Man+Work.h"
@implementation Man (Work)+ (void)load{
    NSLog(@"call Man (Work) load");
}
@end
Copy the code

Running the program and looking at the console output, you can see that the category load method call always follows the class load method call.

call man load
call Man (Work) load
call man initialize
Copy the code

conclusion

Through some code examples and official documentation, we can see that the initialize method is used to initialize a class before it receives its first message. The load method is called when the class or category is added to the Runtime. The load method is called before the Initialize method.

reference

  1. https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?preferredLanguage=occ
  2. https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc
  3. http://zhangbuhuai.com/initialize-and-load-in-objective-c/