文章目录
OC对象 - Category(分类)
1. Category的底层结构
位于objc-runtime-new.h
从底层结构可以看出
- 分类中有
实例方法
和类方法
列表 - 没有成员变量(ivar),因此不能给分类添加成员变量
- 在分类里面声明的属性,不会自动生成 get/set 方法,除非使用
关联对象
(后续会讲)
2. Category的实现原理
- Category编译之后的底层结构是struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息
- 在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象、元类对象中)
2. Category的加载处理过程
- 通过Runtime加载某个类的Category数据
- 把所有Category的方法、属性、协议数据,合并到一个大数组中
-
- 后面参与编译的Category数据,会在数组的前面
- 将合并后的分类数据(风格发、属性、协议),插入到类原来数据的前面
2.1 重点:数据和合并
我们有必要记住这个分类数据的合并顺序,下面将通过示例代码来验证
2.1.1 某个类仅有一个分类的时
假设我们有ZSXPerson类,其中有sayHello
方法,有一个ZSXPerson的分类,ZSXPerson+Test
,重写了sayHello
方法
- 所有分类数据会先合并到一个大数组中,再插入到原来数据的前面
- 此时分类如果重写了父类的方法,最后调用方法都会优先找到分类的方法实现来调用。(相当于覆盖掉父类的方法)
2.1.2 某个类有多个分类的时
假设有多个ZSXPerson的分类,他们都重写了sayHello
方法
- 所有分类数据会先合并到一个大数组中,再插入到原来数据的前面,分类按照编译顺序,
先编译
的分类数据在后面
,后编译
的分类数据在前面
,再插入到原来数据的前面 - 这时候
sayHello
方法优先被找到的应该是最后一个被编译的分类的方法实现
这是当前的类文件,将按从上往下的顺序
最后一个编译的类是ZSXPerson+Test
,所以运行时sayHello
应该要调用ZSXPerson+Test
的方法实现
2.1.3 调整编译顺序
可以拖动这个列表,来调整类的编译顺序,此时我们把ZSXPerson+66
类调整到最下面
可以看到,此时sayHello
调用的是ZSXPerson+66
的方法实现
@oubijiexi