+load和+initialize
+load
与 +initialize
的异同
-
+load
方法会在 main() 函数之前调用,而+initialize
是在类第一次使用时才会调用 -
+load
方法调用优先级:父类>子类>分类,并且不会被覆盖,均会调用 -
+initialize
调用优先级:分类>父类,父类>子类,父类的分类重写了+initialize
方法会覆盖父类的+initialize
方法。即:- 如果分类和父类均实现了
+initialize
,则只有分类的+initialize
会被调用; - 如果父类和子类均实现了
+initialize
,第一次引用 子类时,先调用父类的+initialize
,再调用子类的+initialize
; - 如果父类实现了
+initialize
,则第一次引用子类时,会调用两次父类的+initialize
- 如果分类和父类均实现了
-
+load
方法在 main() 函数之前调用,所有的类文件都会加载,分类也会加载 - 均无须显式调用 super 方法
load
由于 +load
方法在 App 启动加载的时候调用,此时不能保证所有的类被加载完成。
+load
方法是线程安全的,因为内部有锁,但是也带了一定的性能开销。所以一般会在 +load
方法中实现 Method Swizzle
调用顺序是父类->子类->分类。
多个分类中实现了+load方法,根据Compile Source中的顺序决定。但要遵循调用[ChildClass load]之前,必须先调用其[SuperClass load]方法。
load 方法是直接使用函数指针调用,即走 C 语言函数调用的流程,不是发送消息,并不会走消息转发流程,也就是说如果一个类实现了 load 函数就会调用,如果没有实现也不会调用该类的父类 load 函数。
+initialize
方法
父类->子类,分类会覆盖类,如果子类没有实现 initialize 方法,父类会调用两次
子类实现了 initialize,会先调用父类 initialize,再调用子类 initialize
子类没有实现 initialize,父类 initialize 方法会调用两次
如果先引用父类的实例对象,再引用子类实例对象,则会在引用父类实例对象时调用父类 initialize 方法;当引用子类实例对象时,由于父类的 initialize 方法已经执行,所以此时只调用子类 initialize 方法
如果先引用子类的实例对象,再引用父类的实例对象,则会在引用子类的实例对象时,在调用 initialize 方法前,先调用父类 initialize 方法,再调用子类的 initialize 方法;当引用父类实例对象时,由于在引用子类实例对象时已经调用了 initialzie 方法了,此时不再调用 initialize 方法
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
或者使用 dispatch_once
load 函数的调用直接是函数指针的调用,而 initialize 函数是消息转发。所以 class 的子类就算没有实现 initialize 函数,也会调用父类的 initialize 函数