ios-类的加载过程(_read_images/懒加载类/非懒加载类)
前言:
上篇文章分析了read_images
中的模块含义,实现了非懒加载类
和懒加载类
加载到内存的过程。其中遗留上了一个问题methodizeClass
方法的实现,本篇文章着重分析methodizeClass
方法和分类
的加载过程。
分类的本质:
首先通过clang -rewrite-objc main.m -o main.cpp 看下结构
由此可见
分类的本质,就是一个 _category_t类型的结构体
methodizeClass
- 进入
**methodizeClass**
源码,获取要研究的对象
- rwe中添加方法列表,属性列表,协议
- 粘贴分类
attachToClass实现
rwe的逻辑已methodList为例
rwe的逻辑如下:
-
获取
ro->baseMethods()
-
通过
prepareMethodLists
方法排序 -
rwe->methods.attachLists
插入
排序prepareMethodLists方法探究
- prepareMethodLists
- fixupMethodList
- 验证方法排序
查看kc_ro内容
查看经过**prepareMethodLists**
方法过后排好序的第一个方法
在控制台打印方法列表
按照方法名称排序
按照方法imp地址排序
attachLists:插入
**method_list_t**
继承与**entsize_list_tt**
,是一个二维数组
- attachLists实现
断点进入要研究的对象LGPerson
在attachLists
方法中打个断点
继续跟进
继续断点跟进
由上图可看出,方法列表是如何插入到内存的,hasArray()
同理
所以加载类
是一个一维赋值,路径为:map-images
-> _read_images
-> readClass
-> realizeClassWithoutSwift
-> mehodizeClass
-> prepareMethodLists
-> fizupMethodList
->attachToClass
-> load_categories_nolock
-> attachCategories
-> extAllocIfNeeded
->ectAlloc
-> attachLists
attachCategories分析
继续执行一步,打印mlist
把mlist插入到定义的64位数组的末尾部
rwe -- LGB分类数据加载
继续跟进
进入**attachLists
**方法进行内存加载
综上所述,attachLists
方法主要是将类 和 分类 的数据加载到rwe
中
-
首先加载类的
data
数据,rew
没有值,list
为空,走的是首地址赋值,一维数组
赋值 -
当类加载成功后,添加
分类
,list有值
,走的是1+多个的方式
-
当在加一个分类是。
rew
是一个数组【本类+第一个分类】
,走hasArray
方法,即本类+分类的list
,走多对多流程
流程如下:
分类的加载流程如下图所示:
类和分类的懒加载/非懒加载:
根据懒加载和非懒加载的状态,类和分类有没有懒加载可以分为以下几种情况:
-
类和分类都实现了
load
方法 -
分类实现了load方法,类没有实现load方法
-
类实现了load方法,分类没有实现
-
类和分类都没有实现load方法
总结:
类和分类的加载流程
-
读取类的名称和地址信息
readClass
。 -
根据名称和地址信息,从
Math_O
加载类的属性,方法,协议,到内存中realizeClassWithoutSwift
-
realizeClassWithoutSwift
里面有两个东西:
- 序列化类的方法,协议等信息
- 添加类/分类的数据信息
attachCategories
综上所述,类从Mach-O加载到内存
的流程图如下所示
此图参考《类的加载》