18

在一个子类中,我重写了一个未在超类​​中公开的方法。我知道我有正确的签名,因为它成功地覆盖了超类实现。但是,作为新实现的一部分,我需要从子类的实现中调用超类的实现。

因为它没有暴露,所以我必须通过调用来调用该方法performSelector

SEL superClassSelector = NSSelectorFromString(@"methodToInvoke");
[super performSelector:superClassSelector];

但是,在我的应用程序中,这会导致无限递归循环,每次我尝试调用超类的实现时都会调用子类的实现。

有什么想法吗?

我意识到这是一种非典型情况,但不幸的是,我无法绕过我正在尝试做的事情。

4

3 回答 3

45

我处理这个问题的方法是在你的子类实现文件中用你想从子类调用的方法重新声明你的超类接口

@interface MySuperclass()
- (void)superMethodIWantToCall;
@end

@implementation MySubclass


- (void)whateverFunction  {
    //now call super method here
    [super superMethodIWantToCall];
}

@end

我不确定这是否是最好的做事方式,但它很简单并且对我有用!

于 2013-05-21T20:11:23.083 回答
9

这是行不通的,因为您只是将performSelector:,而不是您传递给它的选择器发送给超类。performSelector:仍然在当前类的方法列表中查找该方法。因此,您最终会得到相同的子类实现。

最简单的方法可能是写在你自己的调用中objc_msgSendSuper()

// Top level (this struct isn't exposed in the runtime header for some reason)
struct objc_super
{
    id __unsafe_unretained reciever;
    Class __unsafe_unretained superklass;
};

// In the subclass's method
struct objc_super sup = {self, [self superclass]};
objc_msgSendSuper(&sup, _cmd, other, args, go, here);

正如 Rob Napier 在下面指出的那样,这在一般情况下可能会导致问题。我基于该方法没有返回值的假设提出了这个建议。

于 2013-05-21T20:18:06.613 回答
2

一种方法是使用您尝试公开的方法在单独的文件中创建类的类别

@interface MyClass (ProtectedMethods)

- (void)myMethod;

@end

在.m

@implementation MyClass (ProtectedMethods)

- (void)myMethod {

}

@end

然后,从您的 .m 文件中导入此类别,一切顺利。这不是最漂亮的东西,但它会做的伎俩

于 2013-05-21T20:04:30.673 回答