用类别覆盖方法时如何调用原始实现?

发布于 2024-10-05 04:08:23 字数 436 浏览 4 评论 0原文

我试图弄清楚事情到底是如何运作的。所以我想当我使用类别覆盖某些方法时,我会得到有趣的 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。

仅供个人学习之用。我想看看事件传递的实际情况。

I try to figure out how things really work. So I thought when I would overwrite certain methods using categories, I would get interesting NSLogs.

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

super and self don't work here. Is there a way to call the original implementation of -hitTest:withEvent:? What I want is an NSLog every time -hitTest:withEvent: is called on an UIView.

It's just for personal learning purposes. I want to see the event delivery in action.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉世弥音 2024-10-12 04:08:23

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

您可以做的是使用 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);

You can do it, but not using a category. A category replaces a method. (Warning, car analogy) If you have a car, and you destroy that car and replace it with a new car, can you still use the old car? No, because it is gone and does not exist anymore. The same with categories.

What you could do is use the Objective-C runtime to add the method under a different name at runtime (say, "bogusHitTest:withEvent:"), then swap the implementations of hitTest:withEvent: and bogusHitTest:withEvent:. That way when the code calls hitTest:withEvent:, it's going to execute the code that was originally written for bogusHitTest:withEvent:. You can then have that code invoke bogusHitTest:withEvent:, which will execute the original implementation.

So the bogus method would look like:

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

The code to swap the methods would be something along the lines of:

Method bogusHitTest = class_getInstanceMethod([UIView class], @selector(bogusHitTest:withEvent:));
Method hitTest = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:));
method_exchangeImplementations(bogusHitTest, hitTest);
离旧人 2024-10-12 04:08:23

您想要做的称为方法调配: http://www.cocoadev.com/index.pl ?方法调配

What you want to do is called method swizzling : http://www.cocoadev.com/index.pl?MethodSwizzling

飞烟轻若梦 2024-10-12 04:08:23

不幸的是,不能,无法调用您重写的方法的原始实现。一旦你在类别中实现它,你就消除了原来的方法。

super 发送相同的消息应该可以在您的方法中工作;它将像平常一样调用超类上的方法(如果有的话)。

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

Unfortunately, no, there is no way to call the original implementation of a method that you override. Once you implement it in the category you have eliminated the original method.

Sending the same message to super should work in your method; it will call the method on the superclass as normal (if there is one).

Sending the same message to self will create an infinite loop, as I'm sure you've discovered.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文