本文由快学吧个人写作,以任何形式转载请表明原文出处
一、材料预备
objc4-818.2
对应mac的版别是11.1。可根据自己的系统版别挑选能够进行调试的源码。
二、思路
- 从app的加载流程的第一章开端,就知道了app在发动的过程中会使用dyld这个动态链接器,将动态库与mach-o可执行文件进行链接,然后调用动态库的初始化函数,在第二章中知道了在最常用的libobjc动态库的初始化函数
_objc_init
中会有dyld的回调函数,将变成镜像的库映射到内存上,也便是map_images。 - 但是在
_dyld_objc_notify_register
这个回调函数中,还有两个函数没有探索,其中之一便是load_images
,根据命名,能够知道是加载镜像。又如同和(+void)load
办法有关。 - load办法比程序的main()函数还要早的调用,是否和
load_images
有关系?还有在上一章,分类的加载中,也发现了load_images
的调用,所以load_images
到底做了什么?
三、load_images源码
中心源码如下图中红框 :
(1).
loadAllCategories
,在上一章和上上章说过了。主要是衔接分类和类、类的rwe的拓荒、现已将分类的数据贴入类的rwe。(2).
prepare_load_methods
: 为load办法的正式调用做预备.(3).
call_load_methods
: 调用一切的load办法。
四、prepare_load_methods源码
效果 : 为类和分类的load办法的调用做预备。
1. 整体逻辑
2. schedule_class_load
将类和类的load办法的IMP包装成一个目标,然后添加到一张表中,表存的是一切的需求加载load办法的类和类对应的load办法的IMP。
中心函数 : add_class_to_loadable_list
。
add_class_to_loadable_list源码 :
loadable_classes
是寄存loadable_class
结构体的数组。
loadable_class
,结构体类型,寄存着类和类的load办法的IMP。
loadable_classes_used
是loadable_classes
的索引,int类型,是个全局静态变量,指的是现已寄存了多少个loadable_class
结构体目标。
loadable_classes_allocated
是记录loadable_classes
的巨细,int类型,也是全局静态变量。
3. add_category_to_loadable_list
分类没有父类,也就不需求先对父类做处理。直接添加到分类的load办法列表中。逻辑和上面的类是相同的。
4. getLoadMethod和_category_getLoadMethod
逻辑是相同的,只说一个。重点便是 : 从类办法中获取load办法的IMP,由于load都是类办法。
5. 小结
prepare_load_methods
是将类和分类别离参加对应的存储load办法的列表中。(1). 类是isa指向的元类的ro中拿到办法列表来获取load办法的IMP。
(2). 分类是从分类自己的结构体内部的
classMethods
获取load办法的IMP。
- 关于类 :
(1). 先处理父类的load办法,将父类先参加列表。然后再处理自己的。
(2). 参加的是
loadable_classes
表,表中寄存的是结构体loadable_class
,结构体的成员是Class和IMP。(3).
loadable_classes
表的初始巨细是16,每次扩容都是 : 原有巨细 * 2 + 16。
- 关于分类 :
(1). 分类没有父类的概念,不需求处理父类,直接处理自己。
(2). 参加的是
loadable_categories
表,表中寄存的是结构体loadable_category
,结构体成员是Category
和IMP。(3).
loadable_categories
表的初始巨细也是16,每次扩容也是 : 原有巨细 * 2 + 16。
五、call_load_methods
效果 : 调用一切类的load列表中的load办法,调用一切分类的load列表中的load办法。
1. 整体逻辑
2. call_class_loads
类的办法调用的循环是在外部进行的循环,由于类是固定的只要1个,其他的类便是其他的类,不会和自己的load有什么关系。
load_method_t
:
便是直接把IMP强转成了函数指针形式,这样就能够直接调用函数,不需求通过objc_msgSend这样的流程。
3. call_category_loads
思路和类的相同,唯一不相同的便是如果在这个过程中,如果有新的分类的load办法参加进来了,就会持续最外面的do…while循环,持续将新参加的load办法也调用。
六、总结
load_images
做了三件工作 :
-
第一次进入的时候,会将分类和类相关,在类的内部拓荒rwe,将分类的数据存储到类的rwe中。
-
调用类和分类的load办法前的预备工作。预备工作便是将类和分类的load办法以及对应的类和分类一一组合成一个结构体,然后别离参加类和分类的待加载load表中。
-
循环调用类和分类的load办法。类的load办法一定在分类之前调用,父类的load办法一定在子类前调用。