iOS 类别和扩展

130 阅读3分钟

1 介绍类别和扩展

  1. OC Category
  • 分类允许在不修改现有的类的情况下向其添加新的方法
  • 可以向现有的类添加实例方法、类方法、甚至可以添加新的属性。但是,无法向类中添加实例变量
  • 可以在不同的文件中为同一个类添加不同的分类,实现代码分离和模块化
  1. OC Extension
  • 扩展是一种特殊的匿名分类,通常用于在类的内部实现中添加私有方法或属性
  • 可以向现有的类添加实例变量、属性和方法,但只能在类的实现文件中使用,并且对外部是不可见的
  • 扩展必须在类的实现文件中定义,并且不可以跨越多个文件
  1. Swift Extension
  • 可以用来向现有的类、结构体、枚举或协议添加新的功能,包括新的方法、计算属性等
  • 类似于 Objective-C 中的分类,但更加灵活,可以添加计算属性、遵循协议等

2 类别中的属性

参考 iOS 关键字

3 类别中的 +load 和 +initialize 的区别

参考 iOS 常用属性和方法总结

4 在同一个类的多个类别中,同名方法的处理

Category 的加载顺序是由编译顺序和链接顺序来确定的,后编译或者后链接的 Category 会覆盖(不是替换)之前的同名方法实现。

例如当一个类存在多个 Category,并且这些 Category 中有相同方法名的 methodA 时,编译器会按照一定的顺序将这些同名方法合并到类中,类的方法列表里会有两个 methodA。在调用时会调用后加载的 Category 中相同方法名的实现。

5 类别的加载过程

加载过程:

  1. 编译阶段:在编译阶段,Category 的方法会被编译成目标文件(.o 文件),但并不会被合并到原有的类中
  2. 链接阶段:在链接阶段,编译后的目标文件会被链接到可执行文件中
  3. 运行时加载:当应用程序启动时,runtime 会通过运行时机制动态加载 Category,并将其合并到原有的类结构中

6 类别与原有类的合并时机

  1. _objc_init: 程序启动并编译后,Runtime 会进行初始化,包括内存分配、线程管理等操作
  2. map_images: 将可执行文件中的 Mach-O 文件映射到内存中,获取各个镜像的信息
  3. map_images_nolock: 对镜像进行处理,包括查找镜像中的 Objective-C 相关信息,并调用 realizeClass 方法,将类信息加载到内存中
  4. read_images: 读取镜像中的所有类的相关信息,包括类名、方法等
  5. reMethodizeClass: 重新整理类的方法,将 Category 中的方法合并到原有类中
  6. attachCategories: 将 Category 中的方法列表、协议列表等与原有的类合并,并最终加入到 class_rw_t 结构体中,实现了 Category 方法的动态加载