ios-类的加载过程(分类的加载)

1,355 阅读2分钟

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实现

断点进入要研究的对象LGPersonattachLists方法中打个断点

继续跟进

继续断点跟进

由上图可看出,方法列表是如何插入到内存的,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里面有两个东西:

  1. 序列化类的方法,协议等信息
  2. 添加类/分类的数据信息attachCategories

综上所述,类从Mach-O加载到内存的流程图如下所示

此图参考《类的加载