返回

objc_msgSend方法查找流程

IOS

在上一篇文章《iOS-底层原理:objc_class 中 cache(十一)原理分析》中,我们分析了 cache 的写入流程。在写入流程之前,还有一个至关重要的步骤,即方法查找。方法查找负责确定要调用的正确方法,这是一个复杂且高效的过程,涉及多个步骤。本文将深入探讨 objc_msgSend 方法查找流程,揭示 Objective-C 中消息传递的底层机制。

方法查找概述

当我们调用一个对象的方法时,编译器实际上会将这个调用转换为一个 objc_msgSend 调用。objc_msgSend 是 Objective-C 运行时库中的一个函数,它负责查找要调用的方法并执行它。方法查找过程可以分为以下几个步骤:

  1. 方法缓存查找 :首先,运行时会检查方法缓存,这是一个存储最近调用的方法的哈希表。如果方法在缓存中,则直接返回该方法。
  2. 类层次遍历 :如果方法不在缓存中,运行时将遍历类的层次结构,从接收消息的对象的类开始。它将检查每个类的类方法表和实例方法表,以查找匹配的方法。
  3. 动态方法解析 :如果在类层次结构中找不到方法,运行时将调用动态方法解析协议。这允许类在运行时动态添加或修改方法。

方法缓存查找

方法缓存是一个哈希表,存储最近调用的方法。当一个方法被调用时,它会被添加到缓存中。下次调用相同的方法时,运行时会先检查缓存,如果找到该方法,则直接返回它。

方法缓存的目的是提高方法查找的性能。由于大多数方法调用都是对最近调用的方法的重复调用,因此缓存可以避免不必要的类层次遍历和动态方法解析。

类层次遍历

如果方法不在缓存中,运行时将遍历类的层次结构,从接收消息的对象的类开始。对于每个类,它将检查以下两个表:

  1. 类方法表 :存储类的类方法(静态方法)。
  2. 实例方法表 :存储类的实例方法(非静态方法)。

运行时将检查每个表中的方法,以查找与消息选择器匹配的方法。消息选择器是一个唯一标识符,用于标识一个方法。

类层次遍历是一个递归过程,从接收消息的对象的类开始。如果在该类中找不到该方法,运行时将遍历父类,依此类推,直到找到该方法或达到根类。

动态方法解析

如果在类层次结构中找不到该方法,运行时将调用动态方法解析协议。这个协议允许类在运行时动态添加或修改方法。

动态方法解析协议有两个方法:

  1. resolveInstanceMethod :用于动态添加或修改实例方法。
  2. resolveClassMethod :用于动态添加或修改类方法。

如果实现了一个动态方法解析方法,则当在类层次结构中找不到方法时,运行时将调用该方法。动态方法解析方法可以添加新的方法,或修改现有方法的实现。

性能优化

方法查找是一个至关重要的性能因素,因为它决定了调用方法的速度。为了优化方法查找的性能,我们可以采用以下策略:

  1. 减少方法调用的次数 :尽量减少不必要的函数调用,因为每个函数调用都涉及方法查找过程。
  2. 使用缓存 :方法缓存可以显着提高方法查找的性能,因此,充分利用缓存非常重要。
  3. 优化类层次结构 :类的层次结构应尽可能扁平,以减少类层次遍历的深度。
  4. 避免动态方法解析 :动态方法解析虽然提供了灵活性,但它也会增加方法查找的开销。因此,应尽量避免使用动态方法解析。

总结

objc_msgSend 方法查找流程是一个复杂且高效的过程,涉及多个步骤。通过理解这个过程,我们可以更好地理解 Objective-C 中消息传递的原理,并优化我们的代码以获得更好的性能。