返回
iOS底层之从_objc_msgSend到lookUpImpOrForward
IOS
2024-01-26 15:31:18
iOS底层之从_objc_msgSend
到lookUpImpOrForward
在上一篇文章中,我们讨论了_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
。其实现过程如下:
-
查找方法实现:
- 根据
sel
和cls
调用resolveInstanceMethod
函数,查找对应的方法实现(如果有的话)。 - 如果找到方法实现,则将该实现返回。
- 如果找不到方法实现,则返回
NULL
。
- 根据
-
如果未找到方法实现:
- 检查
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底层的消息发送机制,并编写更加健壮、动态的代码。