动态方法解析
Dynamic Method Resolution
我知道如果在 class 或其超 classes 中找不到方法的实现,运行时会提供执行消息的机会。它首先将消息 + (BOOL)resolveInstanceMethod:(SEL)name
发送到对象的 class:此方法允许您在运行时将方法添加到 class:如果此消息 returns是的,这意味着它可以从 + (BOOL)resolveInstanceMethod:(SEL)name
重新发送 message.i 尝试到 return 否,我认为这将使 -(id)forwardingTargetForSelector:(SEL)aSelector
被调用(并且 dynamicMethodIMP
不会被调用被调用),但仍会调用 dynamicMethodIMP
,因为 return 值为 YES。 Apple Doc 说
If the method returns NO, the Objective-C runtime will pass control to the method forwarding mechanism(https://developer.apple.com/library/mac/releasenotes/Foundation/RN-FoundationOlderNotes/)
return YES 和 return No 有什么区别
+ (BOOL)resolveInstanceMethod:(SEL)name
。
一段这样的示例代码:
`void dynamicMethodIMP(id self, SEL _cmd) {
NSLog(@"%@ has added", NSStringFromSelector(_cmd));
}
+(BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(mustHas)) {
class_addMethod([self class], sel, (IMP) dynamicMethodIMP, "v@:");
return NO;
}
return [super resolveInstanceMethod:sel];
}`
[obj mustHas];
您正在阅读的文档来自 10.5 发行说明,但该特定声明不属于 current documentation。
class_resolveInstanceMethod()
的实现实际上忽略了您的 return 值。它只是检查您是否已实现 +resolveInstanceMethod
,如果已实现则调用它,然后查找原始选择器(只是为了缓存结果)。您的 return 值唯一重要的时候是调试运行时。
无需猜测消息转发的工作原理。这都是开源的。这是调用 +resolveInstanceMethod
(runtime/objc-class.mm) 的函数:
/***********************************************************************
* _class_resolveInstanceMethod
* Call +resolveInstanceMethod, looking for a method to be added to class cls.
* cls may be a metaclass or a non-meta class.
* Does not check if the method already exists.
**********************************************************************/
static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst)
{
if (! lookUpImpOrNil(cls->ISA(), SEL_resolveInstanceMethod, cls,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/))
{
// Resolver not implemented.
return;
}
BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
BOOL resolved = msg(cls, SEL_resolveInstanceMethod, sel);
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveInstanceMethod adds to self a.k.a. cls
IMP imp = lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/);
if (resolved && PrintResolving) {
if (imp) {
_objc_inform("RESOLVE: method %c[%s %s] "
"dynamically resolved to %p",
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel), imp);
}
else {
// Method resolver didn't add anything?
_objc_inform("RESOLVE: +[%s resolveInstanceMethod:%s] returned YES"
", but no new implementation of %c[%s %s] was found",
cls->nameForLogging(), sel_getName(sel),
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel));
}
}
}
我知道如果在 class 或其超 classes 中找不到方法的实现,运行时会提供执行消息的机会。它首先将消息 + (BOOL)resolveInstanceMethod:(SEL)name
发送到对象的 class:此方法允许您在运行时将方法添加到 class:如果此消息 returns是的,这意味着它可以从 + (BOOL)resolveInstanceMethod:(SEL)name
重新发送 message.i 尝试到 return 否,我认为这将使 -(id)forwardingTargetForSelector:(SEL)aSelector
被调用(并且 dynamicMethodIMP
不会被调用被调用),但仍会调用 dynamicMethodIMP
,因为 return 值为 YES。 Apple Doc 说
If the method returns NO, the Objective-C runtime will pass control to the method forwarding mechanism(https://developer.apple.com/library/mac/releasenotes/Foundation/RN-FoundationOlderNotes/)
return YES 和 return No 有什么区别
+ (BOOL)resolveInstanceMethod:(SEL)name
。
一段这样的示例代码:
`void dynamicMethodIMP(id self, SEL _cmd) {
NSLog(@"%@ has added", NSStringFromSelector(_cmd));
}
+(BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(mustHas)) {
class_addMethod([self class], sel, (IMP) dynamicMethodIMP, "v@:");
return NO;
}
return [super resolveInstanceMethod:sel];
}`
[obj mustHas];
您正在阅读的文档来自 10.5 发行说明,但该特定声明不属于 current documentation。
class_resolveInstanceMethod()
的实现实际上忽略了您的 return 值。它只是检查您是否已实现 +resolveInstanceMethod
,如果已实现则调用它,然后查找原始选择器(只是为了缓存结果)。您的 return 值唯一重要的时候是调试运行时。
无需猜测消息转发的工作原理。这都是开源的。这是调用 +resolveInstanceMethod
(runtime/objc-class.mm) 的函数:
/***********************************************************************
* _class_resolveInstanceMethod
* Call +resolveInstanceMethod, looking for a method to be added to class cls.
* cls may be a metaclass or a non-meta class.
* Does not check if the method already exists.
**********************************************************************/
static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst)
{
if (! lookUpImpOrNil(cls->ISA(), SEL_resolveInstanceMethod, cls,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/))
{
// Resolver not implemented.
return;
}
BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
BOOL resolved = msg(cls, SEL_resolveInstanceMethod, sel);
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveInstanceMethod adds to self a.k.a. cls
IMP imp = lookUpImpOrNil(cls, sel, inst,
NO/*initialize*/, YES/*cache*/, NO/*resolver*/);
if (resolved && PrintResolving) {
if (imp) {
_objc_inform("RESOLVE: method %c[%s %s] "
"dynamically resolved to %p",
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel), imp);
}
else {
// Method resolver didn't add anything?
_objc_inform("RESOLVE: +[%s resolveInstanceMethod:%s] returned YES"
", but no new implementation of %c[%s %s] was found",
cls->nameForLogging(), sel_getName(sel),
cls->isMetaClass() ? '+' : '-',
cls->nameForLogging(), sel_getName(sel));
}
}
}