Category
结构
_category_t :底层用来存储分类信息的结构
struct _category_t {
const char *name; //用来存放类名
struct _class_t *cls;
const struct _method_list_t *instance_methods; //用来存放category里
面的实例方法列表
const struct _method_list_t *class_methods; //用来存放category里面
的类方法列表
const struct _protocol_list_t *protocols; //用来存放category里面的协议
列表
const struct _prop_list_t *properties; //用来存放category里面的属性列
表
};
创建分类 CLPerson+Test
会自动生成结构体:_OBJC_$_CATEGORY_CLPerson_$_Test
struct _category_t _OBJC_$_CATEGORY_CLPerson_$_Test
分类结构体中 记录着对应的 分类名称,实例方法,类方法,协议,属性 等等
创建分类的整个过程没有新的类生成,只是运行时阶段合并了方法
方法合并
两个分类实现相同方法, 并且原类也有age 和run 方法
CLPerson
实现实例方法 - age
实现类方法 + run
下面简称 age方法0
下面简称 run方法0
创建分类
CLPerson+Test
实现实例方法 - age
实现类方法 + run
下面简称 age方法1
下面简称 run方法1
CLPerson+Test2
实现实例方法 - age
实现类方法 + run
下面简称 age方法2
下面简称 run方法2
编译阶段
先编译 CLPerson+Test ,再编译 CLPerson+Test 2
编译的顺序由文件在Xcode中上下位置有关
生成对应 _category_t 变量
Runtime阶段
CLPerson 类对象实例方法列表 插入 Test 的 age 方法,再 插入Test 2 的age
方法。
更新缓存
CLPerson 的元类对象 的类方法列表,插入 run 1,run 2
实例方法 age 调用顺序
调用的是 age方法2
其它两个方法没有机会,尽管没有被覆盖
--> age2 --> age1 --> age0 -->
最后被编译的类排在前面,优先被调用
类方法run 调用
只有run 2被调用,其它不在上层的方法没有机会
--> run2 --> run1 --> run0 -->
最后被编译的类排在前面,优先被调用
如何控制分类的编译顺序?
在Build Phase->Compile Sources里面调整,直接拖拽