是否有可能找到class_getInstanceMethod
检索到的方法来自类层次结构的位置?例如,假设A类实现了myMethod。现在说我已经在A1类中继承了A类。如果我调用class_getInstanceMethod(ClassA1, myMethod)
,是否可以判断结果方法是否已在ClassA1中被覆盖或直接来自A1?
如果你有权访问ClassA和ClassA1,我想可以比较一下IMP的内存地址,但是我没有直接访问A.
答案 0 :(得分:15)
您始终可以访问类的超类,因此您可以使用相同的class_getInstanceMethod
将其传递给class_getMethodImplementation
或SEL
,并比较IMP
地址以查看是否该方法被子类覆盖。
如果你想进入定义这种方法的根类,这会有点毛茸茸。
无论如何,这里是:
static inline BOOL isInstanceMethodOverridden(Class cls, SEL selector, Class *rootImpClass) {
IMP selfMethod = class_getMethodImplementation(cls, selector);
BOOL overridden = NO;
Class superclass = [cls superclass];
while(superclass && [superclass superclass]) {
IMP superMethod = class_getMethodImplementation(superclass, selector);
if(superMethod && superMethod != selfMethod) {
overridden = YES;
if(!rootImpClass) {
//No need to continue walking hierarchy
break;
}
}
if(!superMethod && [cls respondsToSelector:selector])) {
//We're at the root class for this method
if(rootImpClass) *rootImpClass = cls;
break;
}
cls = superclass;
superclass = [cls superclass];
}
return overridden;
}
答案 1 :(得分:3)
这是我对雅各布代码的修改版本。我遇到了他的问题因为class_getMethodImplementation正在返回一个_objc_msgForward,它导致方法被视为被覆盖。我也不需要* rootImpClass,但它很简单,可以重新添加。
inline BOOL isInstanceMethodOverridden(Class cls, SEL selector)
{
IMP selfImplementation = class_getMethodImplementation(cls, selector);
BOOL overridden = NO;
Class superclass = cls;
while ((superclass = [superclass superclass]))
{
Method superMethod = class_getInstanceMethod(superclass, selector);
if (superMethod && method_getImplementation(superMethod) != selfImplementation)
{
overridden = YES;
break;
}
}
return overridden;
}