咱们在上一篇iOS底层原理之类的加载中探索了关于类的加载
,在结尾部分咱们也注意到了处理分类的代码,此次咱们研究下分类的加载。markdown
研究分类的加载,咱们先看下分类的本质。函数
咱们在源码中搜索category_t
,搜索结果以下从上面咱们能够获得分类的本质是
category_t
结构体,结构体里面有name
、cls
、实例方法列表
、类方法列表
、协议列表
、属性列表
、类属性列表
、元类
等信息,其中正由于分类中有属性列表
,因此分类才能够动态添加 属性
(分类只能声明属性,因为没有set、get方法,因此须要动态添加
)。post
咱们以LGPerson
为主类,咱们添加LGPerson+LGA
和LGPerson+LGB
两个分类。 咱们从上一篇类的加载中得知最终会经过realizeClassWithoutSwift
函数将类的信息关联起来,而realizeClassWithoutSwift
函数经过methodizeClass
函数来处理分类。spa
methodizeClass
函数分析从
methodizeClass
函数中咱们能够看到最终是经过attachToClass
函数来将分类
添加到主类
上的。3d
attachToClass
函数咱们查看attachToClass
函数代码从中能够看到
attachToClass
函数最终又调用了
attachCategories
函数code
attachCategories
函数这个函数里面处理了分类的方法、属性、协议等。orm
attachCategories
函数中的LGPerson
判断部分,运行代码到断点位置,打印堆栈信息分类加载反推路径
为attachCategoriyes
-> load_categories_nolock
(执行两次) -> loadAllCategories
-> load_images
主类跟分类混合加载主要区分在是不是懒加载类,便是否实现了+load
函数get
咱们在main函数中打下断点,如图所示咱们发现此时仅仅执行了
readClsss
函数,经过咱们前面dyld与objc的关联
咱们知道,这个readClass
函数在编译阶段就会执行,所以得知此时并无加载类和其分类
。咱们继续执行代码到NSLog处,此时咱们发现已经加载了
类和其分类
,所以咱们能够总结出来:懒加载类与懒加载分类混合,加载实际推迟到第一次消息转发时,即本文中的[LGPerson alloc]时
源码
仍是同懒加载类与懒加载分类混合
分析相同,从图中咱们发现还有执行
[LGPerson alloc]
时,类已经被加载了,即在编译阶段
就已经被加载了it
从上图中咱们得知也是在
编译阶段
加载了,只是在attachToClass
函数中执行了两次load_categories_nolock
函数
从上图中得知
懒加载类与分懒加载分类混合时,会迫使主类在编译阶段加载