返回

iOS底层之从_objc_msgSend到lookUpImpOrForward

IOS

iOS底层之从_objc_msgSendlookUpImpOrForward

在上一篇文章中,我们讨论了_objc_msgSend的快速查找机制。如果sel能够直接找到对应的imp,则直接执行该imp;如果找不到对应的imp,则执行missLabelDynamic。本文将深入探讨missLabelDynamic的实现细节。

missLabelDynamic的实现

missLabelDynamic函数位于objc-runtime-new.h头文件中,其定义如下:

IMP missLabelDynamic(id self, SEL sel, Class cls, IMP undefImp)

其中:

  • self:消息接收者对象
  • sel:消息选择器
  • cls:消息接收者的类
  • undefImp:找不到imp时的默认实现

missLabelDynamic函数的目的是在找不到对应imp时,通过动态方法解析查找并执行正确的imp。其实现过程如下:

  1. 查找方法实现:

    • 根据selcls调用resolveInstanceMethod函数,查找对应的方法实现(如果有的话)。
    • 如果找到方法实现,则将该实现返回。
    • 如果找不到方法实现,则返回NULL
  2. 如果未找到方法实现:

    • 检查cls是否实现了forwardInvocation:方法。
    • 如果实现了forwardInvocation:方法,则调用该方法,将消息转发给其他对象。
    • 如果未实现forwardInvocation:方法,则返回undefImp,执行默认实现。

示例代码

以下是一个示例代码,演示了missLabelDynamic函数的调用:

id self = [MyClass new];
SEL sel = @selector(myMethod);
IMP undefImp = NULL;

IMP imp = missLabelDynamic(self, sel, [self class], undefImp);
if (imp) {
    // 找到方法实现,调用该实现
    (void)imp(self, sel);
} else {
    // 未找到方法实现,执行默认实现
    NSLog(@"方法未实现");
}

在该示例中,我们创建了一个MyClass实例,并尝试调用一个不存在的方法myMethod。由于MyClass没有实现myMethod,因此resolveInstanceMethod返回NULL。由于MyClass也没有实现forwardInvocation:方法,因此missLabelDynamic返回undefImp,执行默认实现(打印一条日志消息)。

结论

missLabelDynamic函数是_objc_msgSend机制的重要组成部分。它允许动态查找和执行方法实现,从而确保对象能够响应消息,即使该消息对应的imp在编译时不可用。通过理解missLabelDynamic的实现,我们可以深入了解iOS底层的消息发送机制,并编写更加健壮、动态的代码。

附加信息