文章目录
OC对象 - +load、initialize方法
1. +load方法
1.1 调用时机
- +load方法会在runtime加载类、分类时调用
- 每个类、分类的+load,在程序运行时只调用一次
1.2 调用顺序
- 先调用父类的+load
- 按照编译先后顺序调用(先编译,先调用)
- 调用子类的+load之前会先调用父类的+load
- 再调用分类的+load
- 按照编译先后顺序调用(先编译,先调用)
1.3 码上验证
从类文件列表看到,ZSXPerson在其两个分类的后面编译的,但是它的+load始终是最先调用的
1.4 调用方式
从源码可以看出
+load方法是根据方法地址直接调用,并不是经过objc_msgSend函数调用
2. initialize方法
2.1 调用时机
- +initialize方法会在类第一次接收到消息时调用
2.2 调用顺序
- 先调用父类的+initialize,再调用子类的+initialize
- 先初始化父类,再初始化子类,每个类只会初始化1次
注:如果有分类的情况,
分类
的+initialize方法
会覆盖掉类
的+initialize
方法
2.3 码上验证
2.3.1 验证父类和子类的情况
ZSXStuden
是ZSXPerson
的子类,给ZSXStuden
发送消息,先执行父类ZSXPerson
的+initialize
方法,再执行子类ZSXStuden
的+initialize
方法
2.3.4 验证含有分类的情况
ZSXStuden
是ZSXPerson
的子类,ZSXPerson
有分类ZSXPerson+_11
,分类中也实现了+initialize
方法。给ZSXStuden
发送消息,因为分类方法覆盖了类的方法,会先执行父类分类ZSXPerson+_11
的+initialize
方法,再执行子类ZSXStuden
的+initialize
方法
2.4 调用方式
我们注意到,+initialize
实在第一次收到消息时调用,可以推断出他是跟runtime
有关的,所以:
+initializ
e是通过objc_msgSend
进行调用的
3. +load、initialize方法的区别
+initialize和+load的很大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点
- 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
- 如果分类实现了+initialize,就覆盖类本身的+initialize调用
3.1 验证+initialize可能被调用多次
因为+initialize
走了runtime机制调用,我们知道,子类收到消息时,如果自身找不到方法实现,会到父类中继续查找
- 我们多创建一个
ZSXPerson
的子类ZSXTeacher
ZSXPerson
有2个子类:ZSXStuden
和ZSXTeacher
ZSXTeacher
中没有+initialize
方法- 我们分别给
ZSXStuden
和ZSXTeacher
发送消息,查看+initialize
方法调用情况、
@oubijiexi