Objective-C中+(void)load和+(void)i
2018-07-02 本文已影响16人
IUVO
参照完这两篇文章(Objective-C 深入理解 +load 和 +initialize以及一道题搞清楚Objective-C中load和initialize)后,自己也大概总结了一下。
首先,验证过程很简单,先建立继承自NSObject
的Person
类,实现+(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()
:一般用于初始化全局变量或静态变量。