文章目录
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
本文详细解释了Objective-C中的Category的底层结构、如何在编译过程中合并数据以及编译顺序对方法覆盖的影响。重点讲解了单一分类、多分类情况下的数据合并和方法调用规则。
1544





