Как вызвать оригинальную реализацию при переписывании метода с категорией? - PullRequest
6 голосов
/ 28 ноября 2010

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

@implementation UIView(Learning)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"-hitTest:withEvent: event=%@", event);
    return [self hitTest:point withEvent:event];
}
@end

super и self здесь не работают.Есть ли способ вызвать оригинальную реализацию -hitTest: withEvent :?Мне нужен NSLog каждый раз, когда -hitTest: withEvent: вызывается в UIView.

Это просто для личных целей обучения.Я хочу увидеть доставку события в действии.

Ответы [ 3 ]

14 голосов
/ 28 ноября 2010

Вы можете сделать это, но не используя категорию.Категория заменяет метод.(Предупреждение, аналогия с автомобилем) Если у вас есть машина, и вы уничтожаете эту машину и заменяете ее новой, можете ли вы по-прежнему использовать старую машину?Нет, потому что он ушел и больше не существует.То же самое с категориями.

Что вы можете сделать, это использовать среду выполнения Objective C, чтобы добавить метод под другим именем во время выполнения (скажем, "bogusHitTest:withEvent:"), а затем поменять местами реализации hitTest:withEvent:и bogusHitTest:withEvent:.Таким образом, когда код вызывает hitTest:withEvent:, он выполняет код, изначально написанный для bogusHitTest:withEvent:.Затем вы можете заставить этот код вызывать bogusHitTest:withEvent:, который будет выполнять исходную реализацию.

Таким образом, фиктивный метод будет выглядеть следующим образом:

- (UIView *) bogusHitTest:(CGPoint)point withEvent:(UIEvent *)event {
  NSLog(@"executing: %@", NSStringFromSelector(_cmd));
  return [self bogusHitTest:point withEvent:event];
}

Код для замены методов будет чем-то вродевдоль линий:

Method bogusHitTest = class_getInstanceMethod([UIView class], @selector(bogusHitTest:withEvent:));
Method hitTest = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:));
method_exchangeImplementations(bogusHitTest, hitTest);
3 голосов
/ 28 ноября 2010

То, что вы хотите сделать, называется методом Swizzling: http://www.cocoadev.com/index.pl?MethodSwizzling

0 голосов
/ 28 ноября 2010

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

Отправка того же сообщения на super должна работать в вашем методе; он будет вызывать метод в суперклассе как обычно (если он есть).

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

...