1 介绍类别和扩展
- OC Category
- 分类允许在不修改现有的类的情况下向其添加新的方法
- 可以向现有的类添加实例方法、类方法、甚至可以添加新的属性。但是,无法向类中添加实例变量
- 可以在不同的文件中为同一个类添加不同的分类,实现代码分离和模块化
- OC Extension
- 扩展是一种特殊的匿名分类,通常用于在类的内部实现中添加私有方法或属性
- 可以向现有的类添加实例变量、属性和方法,但只能在类的实现文件中使用,并且对外部是不可见的
- 扩展必须在类的实现文件中定义,并且不可以跨越多个文件
- Swift Extension
- 可以用来向现有的类、结构体、枚举或协议添加新的功能,包括新的方法、计算属性等
- 类似于 Objective-C 中的分类,但更加灵活,可以添加计算属性、遵循协议等
2 类别中的属性
3 类别中的 +load 和 +initialize 的区别
4 在同一个类的多个类别中,同名方法的处理
Category 的加载顺序是由编译顺序和链接顺序来确定的,后编译或者后链接的 Category 会覆盖(不是替换)之前的同名方法实现。
例如当一个类存在多个 Category,并且这些 Category 中有相同方法名的 methodA 时,编译器会按照一定的顺序将这些同名方法合并到类中,类的方法列表里会有两个 methodA。在调用时会调用后加载的 Category 中相同方法名的实现。
5 类别的加载过程
加载过程:
- 编译阶段:在编译阶段,Category 的方法会被编译成目标文件(.o 文件),但并不会被合并到原有的类中
- 链接阶段:在链接阶段,编译后的目标文件会被链接到可执行文件中
- 运行时加载:当应用程序启动时,runtime 会通过运行时机制动态加载 Category,并将其合并到原有的类结构中
6 类别与原有类的合并时机
- _objc_init: 程序启动并编译后,Runtime 会进行初始化,包括内存分配、线程管理等操作
- map_images: 将可执行文件中的 Mach-O 文件映射到内存中,获取各个镜像的信息
- map_images_nolock: 对镜像进行处理,包括查找镜像中的 Objective-C 相关信息,并调用
realizeClass方法,将类信息加载到内存中 - read_images: 读取镜像中的所有类的相关信息,包括类名、方法等
- reMethodizeClass: 重新整理类的方法,将 Category 中的方法合并到原有类中
- attachCategories: 将 Category 中的方法列表、协议列表等与原有的类合并,并最终加入到
class_rw_t结构体中,实现了 Category 方法的动态加载