美文网首页iOS Developer
oc runtime _class_resolveMethod

oc runtime _class_resolveMethod

作者: 2d899c5242bd | 来源:发表于2017-08-21 00:05 被阅读561次

函数原型如下

/***********************************************************************
* _class_resolveMethod
* Call +resolveClassMethod or +resolveInstanceMethod.
* Returns nothing; any result would be potentially out-of-date already.
* Does not check if the method already exists.
**********************************************************************/
void _class_resolveMethod(Class cls, SEL sel, id inst)
{
    if (! cls->isMetaClass()) {
        // try [cls resolveInstanceMethod:sel]
        _class_resolveInstanceMethod(cls, sel, inst);
    } 
    else {
        // try [nonMetaClass resolveClassMethod:sel]
        // and [cls resolveInstanceMethod:sel]
        _class_resolveClassMethod(cls, sel, inst);
        if (!lookUpImpOrNil(cls, sel, inst, 
                            NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) 
        {
            _class_resolveInstanceMethod(cls, sel, inst);
        }
    }
}

函数功能:在为选择子查找具体IMP的过程中,方法决议阶段调用,提供动态添加方法IMP的机会。

疑问:为什么else会这么写?

_class_resolveClassMethod(cls, sel, inst);
        if (!lookUpImpOrNil(cls, sel, inst, 
                            NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) 
        {
            _class_resolveInstanceMethod(cls, sel, inst);
        }

即为什么查找类方法的实现过程中会查看resolveInstanceMethod的实现。
其根本原因为 NSObject 为root meta class类的根类,而root meta class 为所有其他meta class的 ISA指向的类。在类方法的巡查过程中,通过meta class的继承关系会最终找到NSObject类,所以在NSObject 的resolveInstanceMethod添加方法决议实现代码,并且在类方法(+号方法)的决议过程中检测该实现是合理的。

测试代码


@interface NSObject (haha)

@end

void dynamicMethodIMP(id self, SEL _cmd) {
    NSLog(@" >> dynamicMethodIMP");
}



@implementation NSObject (haha)
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
    if (aSEL == @selector(iOSliang))
    {
        class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
        return YES;
    }
    return NO;
}

@end

@interface MyClass : NSObject
+ (void)iOSliang;
- (void)iOSliang;
@end

@implementation MyClass

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [MyClass iOSliang];
    }
    return 0;
}

测试结果:成功输出log

2017-08-20 23:58:21.475619+0800 ClassAct[30169:1306725] dynamicMethodIMP

如有不对,还望指正。

相关文章

网友评论

    本文标题:oc runtime _class_resolveMethod

    本文链接:https://www.haomeiwen.com/subject/kevqdxtx.html