Objective-C中+(void)load和+(void)initialize差异

参照完这两篇文章(Objective-C 深入理解 +load 和 +initialize以及一道题搞清楚Objective-C中load和initialize)后,自己也大概总结了一下。

首先,验证过程很简单,先建立继承自NSObjectPerson类,实现+(void)load+(void)initialize方法:

+(void)load {
    NSLog(@"Person:%s %@", __FUNCTION__,[self class]);
}

+ (void)initialize {
    NSLog(@"Person:%s %@", __FUNCTION__,[self class]);
}

再创建继承自Person类的Chinese类以及Person类、Chinese类的分类,如上述代码实现+(void)load+(void)initialize方法。
main.m文件中的main()方法打印函数执行时机:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSLog(@"Main start");
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}



运行后显示如下:
运行结果

分两部分来看:

  • +(void)load方法:

    • 执行的顺序是父类->子类->子类分类->父类分类,根据官方文档上说Invoked whenever a class or category is added to the Objective-C runtime;,简单的说就是当类或者分类被加载到Objective-C runtime的时候就会运行,也就是说是在main()之前会根据上述顺序来加载,又因为是直接获取函数指针来执行,不会像objc_msgSend一样会有方法查找的过程。。
    • 官方文档也是这么说的:A class’s +load method is called after all of its superclasses’ +load methods.,就是说类的+load方法会在其所有父类调用完+load方法后再被调用。
    • 官方文档还说的:A category +load method is called after the class’s own +load method.,就是说分类的+load方法会在其类调用完+load方法后再被调用。
    • 同时,每个类的+load方法都只会被调用一次。
  • +(void)initialize方法:

    • 官方文档上说Initializes the class before it receives its first message.,意思是在类接收第一条消息之前初始化类。
    • initialize 最终是通过 objc_msgSend 来执行的,objc_msgSend会执行一系列方法查找。
    • 值得注意的点是:类初始化的时候每个类只会调用一次+initialize(),如果子类没有实现+initialize(),那么将会调用父类的+initialize(),也就是意味着父类的+initialize()可能会被多次调用;如果父类没有实现+initialize(),子类实现+initialize(),则只会调用子类。并且分类的方法会覆盖类中的方法

最后说下使用场景:
+load():通常用来进行Method Swizzle,尽量避免过于复杂以及不必要的代码。
+initialize():一般用于初始化全局变量或静态变量。

你可能感兴趣的:(Objective-C中+(void)load和+(void)initialize差异)