且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-03-15 21:36:18

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

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.

您可以做的是使用Objective-C运行时在运行时以不同的名称添加方法(例如, bogusHitTest:withEvent:),然后交换 hitTest的实现:withEvent: bogusHitTest:withEvent:。这样当代码调用 hitTest:withEvent:时,它将执行最初为 bogusHitTest编写的代码:withEvent:。然后,您可以让代码调用 bogusHitTest:withEvent:,这将执行原始实现。

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.

所以伪造方法如下:

- (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);