Runtime 总结笔记`深入理解Category`

参考文章美团技术博客

文章为原创,转载请注明出处

Category简介

使用Category把类分开在几个不同的文件里,这样做有几个好处
  1. 减少单个文件体积
  2. 把不同的功能组织到不同的Category里
  3. 可以由多个开发者共同完成一个类
  4. 可按需加载要用的Category
  • Category还可以模拟多继承,把frameWork的私有方法分开
  • Category无法添加实例变量
Category 的结构
  • Objective-C类和对象在runtime都是用结构体表示的,Category也一样,在runtime层,Category使用category_t结构体
typedef struct category_t {
	const char *name;
	classref_t cls;
	
	struct method_list_t *instanceMethods;
	struct method_list_t *classMethods;
	struct protocol_list_t *protocols;
	struct property_list_t *instanceProperties;
} category_t;

其中包含了:
1. 类的名字
2. 类
3. category中添加的实例方法列表
4. category中添加的类方法列表
5. category中所实现的protocol表列
6. category中添加的属性

从上面看出Category可以添加(实例方法,类方法,实现协议,添加属性),不能添加实例变量

Category的加载
  1. Category是在runtime进入入口的时候添加到类上面的,runtime遍历Category_t数组,将Category的实例方法,协议,属性添加到类上,把Category的类方法添加到类的metaClass上面
  2. Category方法没有“完全替换“原来类已有的方法,也就是说,如果Category添加了MethodA,原来的类也有同样的方法,那么该类此时有两个MethodA方
  3. Category的方法被放到了新方法列表的前面,在runtime的objc_msgSend查找方法时,找到第一个方法就调用该方法,所以当多个Category重写了同一个方法时,会使用编译时放在后面的Category的方法
Category和+load方法
  1. Category可以覆写类的+load方法,因为类的+load发生在Category的+load方法之前,当多个Category都覆写了+load方法时,Category的+load方法取决于Category文件的编译顺序
Category 和 关联对象

由于Category中无法动态的添加实例变量,所以可以通过关联对象的方法来为类添加实例变量

关联对象存储在一个全局叫AssociationsManager的map里,其中key是被关联对象的指针地址,value存储着另一个静态的全局map,称为AssociationHashMap,这里的key和value分别是设置关联对象时候的Key和Value

class-continuation

  1. 不对外公开的方法和实例变量写在"class-continuation"里,class-continuation只能定义在类的实现文件里
  2. 属性和实例方法也可以定义在这里,定义在这里然后在依次实现会显得明确一点
  3. 将public接口实现的只读方法在这里扩展成可读写方法,以便在内部设置其值,一般不直接访问实例变量,通过设置方法来做,这样可以触发KVO
  4. 对象的协议方法只用设置为私有时在class-continuation里定义
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章