返回

ObjC 底层原理 08 - objc_msgSend 过程探索(二)

IOS

前言

在上节文章中,我们通过汇编代码探索了 objc_msgSend 函数的第一个流程 CacheLookup,了解了如何从缓存中查找消息实现。在本节中,我们将继续深入分析 objc_msgSend 函数,重点关注其第二个流程 CacheLookup NORMAL 和 _objc_msgSend 等分支的运行机制。

CacheLookup NORMAL 流程

当消息没有在缓存中找到时,objc_msgSend 函数会进入 CacheLookup NORMAL 流程。这个流程的主要目的是在类及其父类中搜索消息实现。

1. 获取类的方法列表

首先,objc_msgSend 函数会从接收者对象中获取其所属的类。然后,它会遍历这个类的所有方法列表,包括父类的继承方法,直到找到与消息名称相匹配的方法。

2. 检查方法是否存在

如果在类及其父类中找到了与消息名称相匹配的方法,objc_msgSend 函数会检查该方法是否有效。无效的方法可能是因为该方法被标记为已弃用或因为该方法的参数列表与消息的参数列表不匹配。

3. 调用方法

如果方法有效,objc_msgSend 函数会调用该方法。方法调用会将消息的参数传递给方法,并执行方法的实现。

CacheLookup _objc_msgSend 流程

如果在类及其父类中没有找到与消息名称相匹配的方法,objc_msgSend 函数会进入 CacheLookup _objc_msgSend 流程。这个流程的主要目的是将消息转发给其他对象。

1. 检查类是否有实现 _objc_msgSend 方法

objc_msgSend 函数会检查接收者对象所属的类是否实现了 _objc_msgSend 方法。_objc_msgSend 方法是一个特殊的方法,它允许类处理没有找到的消息。

2. 调用 _objc_msgSend 方法

如果类实现了 _objc_msgSend 方法,objc_msgSend 函数会调用该方法。_objc_msgSend 方法可以将消息转发给其他对象,也可以返回一个错误。

3. 处理返回结果

如果 _objc_msgSend 方法返回一个非空值,objc_msgSend 函数会将消息转发给返回的对象。如果 _objc_msgSend 方法返回一个空值,objc_msgSend 函数会返回一个错误。

性能优化

为了提高 objc_msgSend 函数的性能,Apple 在 iOS 系统中引入了一些优化措施。这些优化措施包括:

1. 消息缓存

objc_msgSend 函数会将最近使用过的消息缓存起来。这样,当同一个消息再次被发送时,objc_msgSend 函数就可以直接从缓存中获取消息的实现,而无需再次搜索类的方法列表。

2. 方法内联

当一个方法被频繁调用时,objc_msgSend 函数可能会将该方法内联到调用代码中。这样,当该方法再次被调用时,objc_msgSend 函数就可以直接执行该方法的实现,而无需进行方法调用。

3. 消息发送优化

在 iOS 8 及更高版本中,Apple 引入了消息发送优化功能。这项优化功能可以减少消息发送时所消耗的内存和 CPU 时间。

总结

通过本节文章的学习,你已经对 objc_msgSend 函数的 CacheLookup NORMAL 和 _objc_msgSend 流程有了更深入的理解。你了解了当消息没有在缓存中找到时,objc_msgSend 函数是如何在类及其父类中搜索消息实现的,以及当类没有实现该消息时,objc_msgSend 函数是如何将消息转发给其他对象的。你