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


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

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

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

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

Какие-нибудь мысли?

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

3 ответа:

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

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

@implementation MySubclass


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

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

Это не работает, потому что вы посылаете только 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);

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

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

@interface MyClass (ProtectedMethods)

- (void)myMethod;

@end

И на своем .m

@implementation MyClass (ProtectedMethods)

- (void)myMethod {

}

@end

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