Objective-C检测类是否覆盖继承的方法

cno*_*gr8 6 inheritance overriding objective-c

有没有办法从子类中动态检测它是否覆盖其父类方法?

Class A {
    - methodRed;
    - methodGreen;
    - methodBlue;
}
Class B inherits A {
    - methodRed;
}
Run Code Online (Sandbox Code Playgroud)

从上面的例子中我想知道B类是否能够动态检测到只有-methodRed;被覆盖.

我想知道这种方法与其他一些可能性的原因是因为我有许多自定义视图会改变它的外观.如果我可以动态检测被覆盖的方法而不是跟踪,那么代码将会少得多.

ipm*_*mcc 17

这是非常简单的测试:

if (method_getImplementation(class_getInstanceMethod(A, @selector(methodRed))) ==
    method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))))
{
    // B does not override
}
else
{
    // B overrides
}
Run Code Online (Sandbox Code Playgroud)

我不得不想知道B如何覆盖A上的方法是有帮助的,但是如果你想知道,这就是你如何发现的.

它也可能值得注意:在最严格的条件下,上面的代码确定B上的选择器的实现是否与A上的选择器的实现不同.如果你有一个像A> X> B和X的层次结构覆盖了选择器,这仍然会报告A和B之间的不同实现,即使B不是重写类.如果你想特别知道"B覆盖这个选择器(不管其他什么)",你会想做:

if (method_getImplementation(class_getInstanceMethod(B, @selector(methodRed))) ==
    method_getImplementation(class_getInstanceMethod(class_getSuperclass(B), @selector(methodRed))))
{
    // B does not override
}
else
{
    // B overrides
}
Run Code Online (Sandbox Code Playgroud)

显然,这可能会问一个问题"B对于选择器有不同的实现而不是超类",这可能是(或许更具体地说)你要求的.

  • 任何使用此代码的人都应该是`#import <objc/runtime.h>` (2认同)
  • 更简单:`class_getMethodImplementation()`可以替换上面的两个链式调用,在某些情况下可能更快.有关详细信息,请参阅https://developer.apple.com/documentation/cocoa/reference/objcruntimeref. (2认同)

Mer*_*ran 11

在您的基类中:

BOOL isMethodXOverridden = [self methodForSelector:@selector(methodX)] !=
                           [BaseClass instanceMethodForSelector:@selector(methodX)];
Run Code Online (Sandbox Code Playgroud)

如果您的子类重写了methodX,则会给出YES.

上面的答案也是正确的,但可能看起来更好.