一:Category的使用场合是什么?
(1)当一个类的功能越来越多,单一类文件的体积会越来越大,甚至出现臃肿的情况
(2)当多人配合开发一个文件时,不可避免的会出现冲突。
(3)当需要给一个已经在程序中很多地方使用,不适合修改和调整类的方法结构时。
使用分类能够做什么?
可以通过给这个类添加分类来减轻单一类文件的功能。
可以通过写不同分类 来减少冲突的实现,
可以通过分类的形式,给类增加 新的方法,而不影响之前类的使用。
二:Category的实现原理
Category 编译之后的底层结构是struct category_t,里面存储着分类的对象方法,类方法,属性,协议信息
在程序运行时,runtime会将Category 的数据,合并到类信息中(包含类和元类的信息更新)
三:Category和Class Extension的区别是什么?
class extension 类拓展,在编译的时候,就会将它的数据包含在类的信息中
Category是在运行的时候,通过runtime 动态的将数据合并到类信息中
四:Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?
Category中可以有load 方法。
Load方法 在runtime 加载类和分类的时候调用
Load方法可以继承,但是一般情况下不会主动去调用load 方法,系统会在加载类的时候自己调用。
Category的加载处理过程
(1)通过Runtime 加载某个类的所有Category数据
(2)把所有的Category的方法,属性,协议数据,合并到一个大数组中。
后面参与编译的Category数据,会在数据的前面
(3)将合并后的分类数据(方法,属性,协议)插入到类原来的数据的前面
+load 方法总结
(1)+load 方法会在runtime加载类,分类的时候调用
(2)每个类,分类的 +laod,在程序运行过程中只调用一次
调用顺序
1. 先调用类的load 方法
按照编译先后顺序调用(先编译,先调用)
调用子类的+load方法之前会先调用父类的+load
2.再调用分类的load方法
按照编译的先后顺序调用,(先编译,先调用)
+load方法是根据方法地址直接调用,并不是经过objc_msgSend函数调用
+initialize 方法 总结
+initialize 方法会在类第一次接收到消息时调用
调用顺序
先调用父类的+initizlize,在调用子类的+initialize
(先初始化父类,在初始化子类,每个类只会初始化1次)
+initialize 与+load的区别
+initialize 是通过objc_msgSend进行调用的,所以有以下特点
如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
如果有分类实现了+initialize,就会覆盖本身的+initialize调用
Category能否添加成员变量?如果可以,如何给Category添加成员变量?
虽然可以给Category 添加属性,但是不能直接给Category 添加成员变量,
但是可以通过关联变量的形式给分类添加成员变量。
添加成员变量后,我们可以像使用成员变量那样去使用这个关联变量,但是这个关联变量并没有存储在实例对象的内存中,而是保存在一个叫AssociationsManager的对象中,该对象是一个字典,字典中的每一个key,value值中保存着 一个对象和这个对象中保存的关联对象的信息。
网友评论