Доступ к методу в суперклассе, когда он не отображается

В подклассе я переопределяю метод, который не отображается в суперклассе. Я знаю, что у меня есть правильная подпись, поскольку она успешно отменяет реализацию суперкласса. Однако, как часть новой реализации, мне нужно вызвать реализацию суперкласса из реализации подкласса.

Поскольку он не отображается, мне нужно вызвать метод с помощью вызова performSelector:

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

Однако в моем приложении это приводит к бесконечному рекурсивному циклу, в котором реализация подкласса вызывается каждый раз, когда я пытаюсь вызвать реализацию суперкласса.

Любые мысли?

Я понимаю, что это нетипичная ситуация, но, к сожалению, нет способа обойти то, что я пытаюсь сделать.

Ответы

Ответ 1

То, как я это рассмотрел, - это повторно объявить интерфейс суперкласса в вашем файле реализации подкласса с помощью метода, который вы хотите вызвать из подкласса

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

@implementation MySubclass


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

@end

Я не уверен, что это лучший способ сделать что-то, но это просто и работает для меня!

Ответ 2

Это не работает, потому что вы отправляете 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 method
struct objc_super sup = {self, [self superclass]};
objc_msgSendSuper(&sup, _cmd, other, args, go, here);

Это может вызвать проблемы в общем случае, как указал Роб Напир ниже. Я предложил это на основании предположения, что метод не имеет возвращаемого значения.

Ответ 3

Один из способов - создать категорию вашего класса в отдельном файле с помощью метода, который вы пытаетесь открыть

@interface MyClass (ProtectedMethods)

- (void)myMethod;

@end

и на .m

@implementation MyClass (ProtectedMethods)

- (void)myMethod {

}

@end

Затем импортируйте эту категорию из своих .m файлов, и вам хорошо идти. Это не самая красивая вещь, но она сделает трюк