Category的加载处理过程
1.通过runtime
动态将分类的方法合并到类对象
、元类
对象中.
2.把所有Category
的方法
、属性
、协议数据
,合并到一个大数组
中。
3.后面参与编译的Category
数据,会在数组
的前面
4.将合并后的分类数据(方法、属性、协议),插入到类原来数据的前面
例子:
首先我们定义GYPerson
、GYPerson+Test1
、GYPerson+Test2
。
同时添加-(void)run;
方法。
会调用哪个
run
方法?这个取决于
编译顺序
。如上述加载过程4
,最后参与编译的方法,会在大数组第一个
,所以它一定不会触发GYPerson
,GYPerson+Test1
、GYPerson+Test2
会触发谁,通过查看编译文件顺序可以得知,如图2调换顺序
,可触发不同分类
中的方法。注意
:就算把GYPerson
移动到最后,也是无法触发GYPerson
中的方法
Category与Class Extend的区别
扩展
的内容在编译的时候就合并到类信息
中,分类
是通过Runtime
再合并。
Category的Load方法
1.+load
方法会在runtime
加载类
、分类
时调用。
2.调用子类
的+load
之前会先调用父类
的+load
。
3.每个类
、分类
的+load
,在程序运行过程中只调用一次
注意:+load
比较特殊,一定是先调用类中load
。在调用分类中的load
。并且不会被分类替代
。通过函数地址
直接调用,所以无编译顺序说法
Category的initialize方法
1.在类
第一次接收到消息
时调用。([GYPerson alloc]
)
之后alloc
,都不会触发
2.先调用父类
,在调用子类
。
注意:+initialize
和+load
的很大区别是,+initialize
是通过objc_msgSend
进行调用的,所以有以下特点:
1.如果子类
没有实现+initialize
,会调用父类
的+initialize
(所以父类的+initialize
可能会被调用多次
)
如果分类
实现了+initialize
,就覆盖
类本身的+initialize
调用