动态方法解析

时间:2015-10-25 12:46:12

标签: ios objective-c dynamic

我知道运行时为消息提供了一个机会,如果在类或超类中找不到该方法的实现。它将通过将消息+ (BOOL)resolveInstanceMethod:(SEL)name发送到对象的类来开始:此方法允许您在运行时将该方法添加到类中:如果此消息返回YES,则表示它可以重新发送消息。从+ (BOOL)resolveInstanceMethod:(SEL)name返回NO,我认为会调用-(id)forwardingTargetForSelector:(SEL)aSelector(并且不会调用dynamicMethodIMP),但仍会调用dynamicMethodIMP和返回值相同是。 Apple Doc说道。

  

如果方法返回NO,则Objective-C运行时将控制传递给方法转发机制(https://developer.apple.com/library/mac/releasenotes/Foundation/RN-FoundationOlderNotes/

返回YES和返回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];

1 个答案:

答案 0 :(得分:0)

您正在阅读的文档来自10.5发行说明,但该特定声明不属于current documentation

class_resolveInstanceMethod()的实施实际上忽略了您的返回值。它只是检查你是否实现了+resolveInstanceMethod,如果你有,则调用它,然后它查找原始选择器(只是为了缓存结果)。返回值唯一重要的是调试运行时。

无需猜测邮件转发的工作原理。这都是开源的。这是调用+resolveInstanceMethodruntime/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));
        }
    }
}