是否可以在不子类化的情况下替换 UIWebView 中现有方法的主体

Posted

技术标签:

【中文标题】是否可以在不子类化的情况下替换 UIWebView 中现有方法的主体【英文标题】:Is it possible to substitute body of existing method in UIWebView without subclassing 【发布时间】:2012-07-05 13:56:26 【问题描述】:

如果可以在运行时替换 UIWebView 的方法体,我很感兴趣? 我不能继承 UIWebView

例如,我需要实现:

- (void) paste:(id)sender;
or
- (BOOL) canPerformAction:(SEL)action withSender:(id)sender;

【问题讨论】:

【参考方案1】:

你试过运行时方法method_setImplementation吗?

像这样:

static IMP originalPaste = NULL;

void myPaste(id rcv, SEL cmd, id sender)

    // Your implementation here


…

    …
    Method m = class_getInstanceMethod([UIWebView class], @selector(paste:));
    originalPaste = method_setImplementation(m, myPaste);
    …

使用originalPaste,您可以在您的实现中执行超级调用。

【讨论】:

酷,正是我在寻找这样的决定。我试过了,但是好像不行,不知道为什么。可能是因为,UIResponderStandardEditActions 是类别( 好吧,忘记我的第一个(已删除)评论。我认为 class_getInstanceMethod() 应该给出当前使用的方法(可能来自类别),但我还没有测试过。如果是这样,method_setImplementation() 应该替换当前使用的方法。那么它不起作用的原因与类别无关。 我已经尝试过 class_replaceMethod(...) 和 method_setImplementation(...) 由于类别的延迟加载或库的动态加载,您的实现替换可能会在稍后被替换。 它认为这是对我问题的正确答案。我可以替换这些方法,但它不能解决 UIMenuController 问题。【参考方案2】:

是的,但不要经常这样做,Apple 说:

虽然目前 Objective-C 语言允许您使用类别来覆盖类继承的方法,甚至是在类接口中声明的方法,但强烈建议您不要这样做。类别不能替代子类。使用类别覆盖方法有几个明显的缺点:

当一个类别重写一个继承的方法时,该类别中的方法可以像往常一样通过消息调用继承的实现给super。但是,如果一个类别覆盖了该类别的类中存在的方法,则无法调用原始实现。

一个类别不能可靠地覆盖在同一类的另一个类别中声明的方法。

这个问题特别重要,因为许多 Cocoa 类是使用类别实现的。您尝试覆盖的框架定义的方法本身可能已经在一个类别中实现,因此没有定义哪个实现优先。

某些类别方法的存在可能会导致所有框架的行为发生变化。例如,如果您在 NSObject 的一个类别中覆盖 windowWillClose: 委托方法,那么您程序中的所有窗口委托都会使用该类别方法进行响应;您的所有 NSWindow 实例的行为可能会改变。您在框架类中添加的类别可能会导致行为的神秘变化并导致崩溃。

除此之外,如果没有子类化,你的生活会变得非常艰难。甚至执行此操作的运行时方式(覆盖 IMP)也会涉及“子类化”(分配类对)。

【讨论】:

带你到this question,那里的文档会很有用。 不,他们是苹果文档。不过,请随意在您的答案中使用它! 完成。在手机上进行复制和粘贴有点棘手! 是的。我等不及他们将 OS 6 纳入主流。也许 SO 最终会让我们有一些类似的编辑沙箱和图像上传功能。 类别不适用于 UIWebView。我在问这个问题,因为它不能以标准方式工作=)

以上是关于是否可以在不子类化的情况下替换 UIWebView 中现有方法的主体的主要内容,如果未能解决你的问题,请参考以下文章

在没有 UIWebView 或 MPMoviePlayer 的情况下播放 .mov 文件

在不使用 UIWebview 的情况下显示 gif 图像 [重复]

在不禁用用户交互的情况下阻止 UIWebView 输入显示 UIKeyboard

没有子类化的 QOpenGLWidget

如何在不加载空页面的情况下清理 UIWebView 的内容?

是否可以在不实际部署映像的情况下在 GCE 上配置容器优化的 OS VM?