+load 方法
- +load 方法会在 runtime 加载类、分类的时候调用
- 每个类、分类的 +load,在程序运行过程中只调用一次
- 可以理解为加载入内存时调用。
调用顺序
- 先调用类的 +load
- 按照编译先后顺序调用(先编译,先调用)
- 调用子类的 +load 之前会先调用父类的 +load
- 再调用分类的 +load
- 按照编译顺序调用(先编译,先调用)
objc4 源码解读过程:objc-os.mm
-
_objc_init
-
load_images
-
1.prepare_load_methods
- schedule_class_load
- add_class_to_loadable_list
- add_category_to_loadable_list
-
2.call_load_methods
- call_class_loads
- call_category_loads
- (*load_method)(cls, SEL_load)
-
+load 方法是根据方法地址直接调用,并不是经过 objc_msgSend 函数调用
[Person load]; 此种调用方式一定会出发 objc_msgSend ( )。isa->superclass->superclass
+initialize 方法
- +initialize 方法会在类第一次接收到消息时调用 objc_msgSend( )。
- 调用顺序:先调用父类的 +initialize 方法,再调用子类的 +initialize 方法
objc_msgSend( )
isa -> 类对象/元类对象,寻找方法,调用
supclass -> 类对象/元类对象,寻找方法,调用
supclass -> 类对象/元类对象,寻找方法,调用
supclass -> 类对象/元类对象,寻找方法,调用
… …
+load 方法,在此类加载到内存中时调用。
+initialize 方法是在寻找方法的时候进行调用,在第一次使用此类的时候想做的事情可以在此方法中处理。
objc4源码解读过程
- objc-msg-arm64.s
- objc_msgSend
- objc-runtime-new.mm
- class_getInstanceMethod
- lookUpImpOrNil
- lookUpImpOrForward
- if (initialize && !cls->isInitialized()) { cls = initializeAndLeaveLocked(cls, inst, runtimeLock);
- initializeAndLeaveLocked
- initializeAndMaybeRelock
- initializeNonMetaClass(nonmeta);
- callInitialize
- objc_msgSend(cls, SEL_initialize)
+load & +initialize 区别
+initilize 和 +load 的最大区别是 +initilize 是通过 objc_msgSend 进行调用的,所以有以下特点:
- 如果子类没有实现 +initilize 方法,会调用父类的 +initilize 方法(所以父类的 +initilize 可能会被调用多次)
- 如果分类实现了 +initilize 方法,就覆盖类本身的 +initilize 调用。