17.iOS应用启动(四):分类的加载
前言
我们在12.类的实现与初始化中实现类 realizeClass
的流程最后一步发现是处理分类 methodizeClass
。本文就将以此为入口,深入探索 什么是分类。
一、 methodizeClass
处理方法列表
、协议列表
、属性列表
,添加分类
。
重要部分见注释:
1.1 attachToClass 将分类添加到类
继续调用
attachCategories
,通过初步阅读源码,发现此处为核心步骤,下面进行具体分析
二、 attachCategories
这里对源码中两处重要的注释做翻译:
添加分类的方法列表、属性、协议到类
最早加载的分类在最顶部
只有很少的类在运行时会有超过
64
个分类这里使用一个小容量的
栈
分类必须按照合适的顺序添加,这里会从前向后读取,从后向前创建本地缓存,并调用
attachLists
。所以最后的顺序是对的。
2.1 流程
extAllocIfNeeded 创建 rwe
循环添加方法、属性、协议
三、 分类加载的时机
我们直到类添加分类的核心逻辑是 attachCategories
。我们全局搜索一下 attachCategories
。
attachToClass
load_categories_nolock
有上面两处进行了调用。
3.1 测试代码准备
自定义类
分类
main函数
3.1 添加断点及日志
3.2 场景一: 分类有Load✅ 主类有Load✅ (非懒加载)
Log如下:
流程:
_read_images
realizeClassWithoutSwift
attachToClass
load_categories_nolock
attachCategories
3.3 场景二: 分类有Load✅ 主类无Load❌ (非懒加载)
Log如下:
流程:
_read_images
realizeClassWithoutSwift
attachToClass
注意到:并没有调用
attachCategories
。
非懒加载
虽然主类未实现+load方法,但是分类实现了,那么主类也是非懒加载的。
3.4 场景三: 分类无Load❌ 主类有Load✅ (非懒加载)
Log如下:
流程:
_read_images
realizeClassWithoutSwift
attachToClass
注意到:和 分类有Load✅ 主类无Load❌ 一样,没有调用
attachCategories
。
3.5 场景四: 分类无Load❌ 主类无Load错❌ (懒加载)
Log如下:
注意到:和 3.3和3.4 一样,没有调用
attachCategories
。
思考: 为什么没有调用 attachCategories
attachCategories
编译器
优化了,直接把分类的数据合并到了主类中。
四、 多分类 +load
执行顺序
+load
执行顺序如果有多个分类,执行的顺序是什么样的呢?
如图创建两个分类,分别实现 +load
方法。思考一下执行的顺序是什么样的呢?为什么呢?
4.1 顺序
按顺序输出如下:
+[RYCat load]
+[RYCat(CateA) load]
+[RYCat(CateB) load]
我们先看下编译顺序:
调整一下编译顺序看有没有影响:
调整编译顺序后输出如下:
+[RYCat load]
+[RYCat(CateB) load]
+[RYCat(CateA) load]
4.2 结论
多分类的情况下,+load
的执行顺序是和编译的顺序有关的。
五、 多分类同名方法执行顺序
如果多个分类由同名的方法,又会是怎样的顺序呢?
在两个分类中声明实现同名的 funcA
在 多分类
+load
执行顺序 中我们知道,编译的顺序影响了各个分类的表现,这里我们也进行一下区分
5.1 CateA 比 CateB 先编译
+[RYCat load]
+[RYCat(CateA) load]
+[RYCat(CateB) load]
-[RYCat(CateB) funcA]
5.2 CateB 比 CateA 先编译
+[RYCat load]
+[RYCat(CateA) load]
+[RYCat(CateB) load]
-[RYCat(CateA) funcA]
5.3 在主类中也声明并实现 funcA (CateB 比 CateA 先编译)
+[RYCat load]
+[RYCat(CateA) load]
+[RYCat(CateB) load]
-[RYCat(CateA) funcA]
5.4 总结
可见:多个分类拥有同名方法
时,先编译的分类的方法
会被后编译的分类
覆盖掉。如果主类中也有同名方法也会被覆盖掉。
思考
对启动速度的影响
在 3.2 主类分类都有实现 Load方法
的时候可见整个流程流程会复杂一下,所以减少这种场景的出现,是有助于提升应用启动速度。
Last updated