函数原型如下
/***********************************************************************
* _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
如有不对,还望指正。
网友评论