返回

iOS Runtime 之 objc_msgSend 慢速查找流程剖析

IOS

导言

在我的上一篇文章《iOS Runtime 之方法的本质:objc_msgSend 分析(一)》中,我们深入研究了 objc_msgSend 的缓存查找(快速查找)流程。在本文中,我们将继续探讨在没有缓存时的方法列表查找(慢速查找)流程,进一步了解 objc_msgSend 的内部机制。

方法列表查找

当 objc_msgSend 无法在缓存中找到方法时,它会转而进行方法列表查找。这个过程涉及到以下步骤:

  1. 类查找: objc_msgSend 从接收者对象中获取其类。
  2. 元类查找: 它使用该类查找其元类。元类包含指向该类方法列表的指针。
  3. 方法列表扫描: objc_msgSend 遍历方法列表,直到找到与消息名称匹配的方法。

缓存失效

缓存查找失败的原因可能是:

  • 方法在类或其父类中未定义。
  • 方法已动态添加或删除。
  • 运行时环境发生了变化。

慢速查找性能优化

为了优化慢速查找的性能,Objective-C 运行时采用了以下技术:

  • 延迟绑定: 方法在第一次被调用时才被绑定到类。这允许运行时动态加载方法,而不需要预先加载整个方法列表。
  • 方法缓存: 当一个方法被找到后,它将被缓存以供将来使用。这减少了后续查找的开销。

示例代码

让我们通过一个示例代码来演示慢速查找流程:

@interface MyClass : NSObject
- (void)myMethod;
@end

@implementation MyClass
- (void)myMethod {
    NSLog(@"Hello from myMethod!");
}
@end

int main() {
    MyClass *myObject = [[MyClass alloc] init];
    [myObject myMethod];
    return 0;
}

在上面的示例中,当 myObject 调用 myMethod 时,objc_msgSend 将首先在缓存中查找该方法。由于这是一个新的方法,因此缓存中不存在。然后,它将执行方法列表查找,并在 MyClass 中找到 myMethod。该方法随后将被绑定到 MyClass 并缓存以供将来使用。

结论

通过了解 objc_msgSend 的慢速查找流程,我们获得了对 Objective-C 运行时方法查找机制的更深入理解。这种方法列表查找虽然比缓存查找速度较慢,但它提供了动态和可扩展的方法查找,是 Objective-C 语言强大功能的关键组成部分。