Доступ к методу в суперклассе, когда он не открыт
В подклассе я переопределяю метод, который не представлен в суперклассе. Я знаю, что у меня есть правильная подпись, поскольку она успешно переопределяет реализацию суперкласса. Однако, как часть новой реализации, мне нужно вызвать реализацию суперкласса из реализации подкласса.
Поскольку он не открыт, я должен вызвать метод с помощью вызова performSelector
:
SEL superClassSelector = NSSelectorFromString(@"methodToInvoke");
[super performSelector:superClassSelector];
Однако в моем приложении это приводит к бесконечному рекурсивному циклу где реализация подкласса вызывается каждый раз, когда я пытаюсь вызвать реализацию суперкласса.
Какие-нибудь мысли?
Я понимаю, что это нетипичная ситуация, но, к сожалению, нет никакого способа обойти то, что я пытаюсь сделать.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 файлов, и вы можете идти. Это не самая красивая вещь, но она сделает трюк