7

我试图弄清楚事情是如何运作的。所以我想当我使用类别覆盖某些方法时,我会得到有趣的 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: 的原始实现?我想要的是每次在 UIView 上调用 -hitTest:withEvent: 时的 NSLog。

仅用于个人学习目的。我想看到事件传递的实际效果。

4

3 回答 3

16

您可以这样做,但不能使用类别。一个类别代替了一个方法。(警告,汽车类比)如果你有一辆车,你把那辆车毁了,换上一辆新车,你还能用旧车吗?不,因为它已经消失,不再存在。类别也是如此。

您可以做的是使用 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);
于 2010-11-28T01:18:22.157 回答
3

你想要做的是方法调配:http: //www.cocoadev.com/index.pl? MethodSwizzling

于 2010-11-28T01:17:39.550 回答
0

不幸的是,不,没有办法调用您覆盖的方法的原始实现。一旦您在类别中实现它,您就消除了原始方法。

发送相同的消息super应该在您的方法中起作用;它将照常调用超类上的方法(如果有的话)。

发送相同的消息self将创建一个无限循环,我相信你已经发现了。

于 2010-11-28T01:05:29.840 回答