在未暴露的情况下访问超类中的方法

Chr*_*son 18 introspection objective-c

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

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

SEL superClassSelector = NSSelectorFromString(@"methodToInvoke");
[super performSelector:superClassSelector];
Run Code Online (Sandbox Code Playgroud)

但是,在我的应用程序中,这会产生一个无限的递归循环,每次我尝试调用超类的实现时都会调用子类的实现.

有什么想法吗?

我意识到这是一种非典型的情况,但不幸的是,我无法绕过我想要做的事情.

Mod*_*try 45

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

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

@implementation MySubclass


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

@end
Run Code Online (Sandbox Code Playgroud)

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


Jos*_*ell 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);
Run Code Online (Sandbox Code Playgroud)

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

  • 通常你不应该调用`objc_msgSend*`,除非有很强的理由这样做.上述代码可能会崩溃或具有错误定义的行为,具体取决于您运行的方法和处理器的确切返回类型.(例如,对于某些方法,您可能必须调用`objc_msgSendSuper_fpret()`.)@ ModernCarpentry的答案是最简单和最正确的方法. (2认同)