在子类中,我重写了一个未在超类中公开的方法。我知道我有正确的签名,因为它成功地覆盖了超类的实现。但是,作为新实现的一部分,我需要从子类的实现中调用超类的实现。
因为它没有暴露,我必须通过调用performSelector
来调用该方法:
SEL superClassSelector = NSSelectorFromString(@"methodToInvoke");
[super performSelector:superClassSelector];
但是,在我的应用程序中,这会产生一个无限的递归循环,每次我尝试调用超类的实现时都会调用子类的实现。
有什么想法吗?
我意识到这是一种非典型的情况,但不幸的是,我无法绕过我想要做的事情。
答案 0 :(得分:45)
我处理这个问题的方法是使用你想从子类调用的方法在你的子类实现文件中重新声明你的超类'接口
@interface MySuperclass()
- (void)superMethodIWantToCall;
@end
@implementation MySubclass
- (void)whateverFunction {
//now call super method here
[super superMethodIWantToCall];
}
@end
我不确定这是不是最好的做事方式,但它很简单,对我有用!
答案 1 :(得分: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在下面指出的那样。我建议这是基于假设该方法没有返回值。
答案 2 :(得分:2)
一种方法是使用您尝试公开的方法在单独的文件中创建类的类别
@interface MyClass (ProtectedMethods)
- (void)myMethod;
@end
和.m
@implementation MyClass (ProtectedMethods)
- (void)myMethod {
}
@end
然后,从您的.m文件中导入此类别,您就可以开始了。这不是最漂亮的事情,但它会做到这一点