返回
Runtime(三)方法缓存
IOS
2023-09-24 10:13:29
1. 方法缓存
1.1 为什么会有方法缓存
在了解类的基本结构之后,本文开始了解探讨 iOS 中的消息发送,即消息调用。首先开始讨论的是——在真正消息调用之前,我们会去方法缓存里面寻找真实的函数地址,iOS 提供的缓存机制用于提高效率。
1.2 方法缓存是什么
方法缓存本质上是一个哈希表,用来存储已经被解析过的selector 和 IMP 的对应关系,存储在 objc_selrefs
中,key 是selector,value 是 IMP(函数指针)。
1.3 方法缓存的存储结构
方法缓存的存储结构为:
struct objc_selrefs {
unsigned int count;
unsigned int size;
SEL *refs;
IMP *imp;
};
count
:已缓存的方法数量。size
:缓存的大小。refs
:指向已缓存的 selector 的指针数组。imp
:指向已缓存的 IMP 的指针数组。
1.4 方法缓存的查找过程
当我们发送消息的时候,首先会去方法缓存里面寻找真实的函数地址,如果找到,则直接调用这个函数地址;如果没有找到,则会去类方法列表里面寻找,如果找到,则把这个函数地址缓存到方法缓存里面,然后调用这个函数地址;如果在类方法列表里面也没有找到,则会去父类的方法列表里面寻找,以此类推,直到找到为止。
2. 方法查找
2.1 方法查找的流程
方法查找的流程如下:
- 在方法缓存里面寻找真实的函数地址。
- 如果在方法缓存里面没有找到,则会去类方法列表里面寻找。
- 如果在类方法列表里面也没有找到,则会去父类的方法列表里面寻找,以此类推,直到找到为止。
2.2 方法查找的优化
为了提高方法查找的效率,iOS 提供了一些优化措施:
- 方法缓存 :方法缓存是一个哈希表,用来存储已经被解析过的 selector 和 IMP 的对应关系,存储在
objc_selrefs
中,key 是 selector,value 是 IMP(函数指针)。 - 类方法列表 :类方法列表是一个数组,用来存储类中的所有方法,存储在
class_ro_t
结构体中,可以通过class_getMethodList()
函数获取。 - 父类的方法列表 :父类的方法列表是一个数组,用来存储父类中的所有方法,存储在
class_ro_t
结构体中,可以通过class_getSuperclass()
函数获取父类,然后通过class_getMethodList()
函数获取父类的方法列表。
3. 总结
方法缓存是一种提高消息发送效率的机制,它可以减少方法查找的时间。方法查找的流程是:首先在方法缓存里面寻找真实的函数地址,如果找到,则直接调用这个函数地址;如果没有找到,则会去类方法列表里面寻找,如果找到,则把这个函数地址缓存到方法缓存里面,然后调用这个函数地址;如果在类方法列表里面也没有找到,则会去父类的方法列表里面寻找,以此类推,直到找到为止。为了提高方法查找的效率,iOS 提供了一些优化措施,包括方法缓存、类方法列表和父类的方法列表。