06.Category原理篇
之前相关知识章节
01.OC实例对象的本质
02.OC有几种对象
03.对象的isa与superclass
category的作用
- 声明私有方法
- 拆解类文件,如NSObject的KVO通知
- 封装方法重复使用
category编译后
我们创建一个分类Person+Test,代码如图:
Person+Test代码可以看到有属性、协议、实例方法、类方法等,接下来直接用终端执行命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc Person+Test.m -o Person+test.cpp
打开编译后的Person+Test.cpp文件,搜索_category_t,可以看到以下代码
category_t的构成通过图片我们可以看到category分类转为_category_t的结构体,结构体包含了名称、属性列表、协议列表、实例方法列表、类方法列表等,既然知道了category的结构,那接下来我们看看是否有用到这个结构体,继续往下找,你会发现有这个东西
使用_category_t定义了一个变量再来看看实例列表有无包含person分类的test方法呢,我们直接复制方法列表名字CATEGORY_INSTANCE_METHODS_Person搜索,可以搜到以下代码
实例方法test的定义看见了"test"没,它被包含在CATEGORY_INSTANCE_METHODS_Person这个变量中,那其他的我们也看看
分类的类方法test 分类的NSCoding协议 分类的name属性上面是从编译后的文件角度来查看category的结构,接下来我们从苹果的源码来窥探category
我们主要查找attachCategories和attachLists这俩个函数,先来看看attachCategories做了些什么
attachCategories函数1 attachCategories函数2看图中我们看到遍历了每一个分类,然后查找每一个分类中的方法、属性、协议等,添加到类上,比如方法还调用了prepareMethodLists,让我们来看看这个函数源码:
prepareMethodLists函数源码可以看到其实有重新分配方法列表,准备好工作后,就开始追加attachLists
attachLists函数源码分类的方法会插入到最前面,源码大概就这样,这里主要讲实现流程,更详细的需要自行去浏览源码,该源码为818版本
总结
编译之后的底层机构是struct category_t,里面存储这分类的对象方法、类方法、属性、协议信息,在程序运行的时候,runtime会将category的数据合并到类信息中(类对象、元类对象中)