二十四、app加载流程(七)load_images

本文由快学吧个人写作,以任何形式转载请表明原文出处

一、资料准备

objc4-818.2

对应mac的版本是11.1。可根据自己的系统版本挑选可以进行调试的源码。

二、思路

  1. 从app的加载流程的第一章开始,就知道了app在启动的过程中会利用dyld这个动态链接器,将动态库与mach-o可执行文件进行链接,然后调用动态库的初始化函数,在第二章中知道了在最常用的libobjc动态库的初始化函数_objc_init中会有dyld的回调函数,将变成镜像的库映射到内存上,也就是map_images。
  2. 但是在_dyld_objc_notify_register这个回调函数中,还有两个函数没有探索,其中之一就是load_images,根据命名,可以知道是加载镜像。又好像和(+void)load方法有关。
  3. 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_usedloadable_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. 小结

  1. prepare_load_methods是将类和分类分别加入对应的存储load方法的列表中。

(1). 类是isa指向的元类的ro中拿到方法列表来获取load方法的IMP。

(2). 分类是从分类自己的结构体内部的classMethods获取load方法的IMP。

  1. 对于类 :

(1). 先处理父类的load方法,将父类先加入列表。然后再处理自己的。

(2). 加入的是loadable_classes表,表中存放的是结构体loadable_class,结构体的成员是Class和IMP。

(3). loadable_classes表的初始大小是16,每次扩容都是 : 原有大小 * 2 + 16。

  1. 对于分类 :

(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做了三件事情 :

  1. 第一次进入的时候,会将分类和类关联,在类的内部开辟rwe,将分类的数据存储到类的rwe中。

  2. 调用类和分类的load方法前的准备工作。准备工作就是将类和分类的load方法以及对应的类和分类一一组合成一个结构体,然后分别加入类和分类的待加载load表中。

  3. 循环调用类和分类的load方法。类的load方法一定在分类之前调用,父类的load方法一定在子类前调用。

相关推荐
HarderCoder3 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
叽哥14 小时前
Flutter Riverpod上手指南
android·flutter·ios
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
权咚2 天前
阿权的开发经验小集
git·ios·xcode
用户092 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间3 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918413 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张3 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h3 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa