【问题标题】:Monkey Patch an Instance in Objective-C猴子在 Objective-C 中修补实例
【发布时间】:2011-03-20 06:56:15
【问题描述】:

我正在尝试遵循here 的(出色的)说明,但我有一个无法通过子类化修改的类实例。有没有办法只覆盖类实例的方法?

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    实际上,您可以使用子类化来修改任何内容。这是您可以做的更微妙的事情之一,您可以查看方法调配(但方法调配会影响类的所有成员),但在目标 c 中,设置任何对象的类都非常容易,所以基本上你需要做的就是声明一个子类,它不声明任何额外的 ivars,只覆盖你需要的方法,(你可能想调用超级实现),然后在运行时通过object_setClass(在 中声明)。

    【讨论】:

      【解决方案2】:

      小心。您即将在 ObjC 中输入一些相当深奥的魔法,而您可以生成的各种错误令人费解。这些是在其他一切都失败后你应该使用的最后一种技术,你应该尽你所能来隔离这段代码。也就是说,ObjC 是一种高度动态的语言,您可以重新连接大多数东西。

      首先,针对您的具体问题,您可以更改实例的类,这将实现您想要的。规则基本上是:

      • 新类应该是前一个类的子类
      • 新类不得添加任何 ivars。在子类中添加 ivars 是导致上述令人费解的错误的原因之一。

      如果您做错了,您将不会收到任何警告或错误。你只会遇到奇怪的崩溃。

      鉴于此,更改对象的类实际上非常简单:

      object->isa = [NewClass class];
      

      除此之外,您还可以使用方法调配为类的每个实例更改方法的实现。我在Hijacking with method_exchangeImplementations() 中有一些这样的例子。不过,一旦您完成此操作,祝您使用调试器好运。

      【讨论】:

      • 谢谢。这很吸引人,但它说服了我坚持自己的优势,不惜一切代价避免这种情况。
      • 其实,看起来还不错,在我的情况下实际上可能会很好。
      • 谨慎使用,其实很简单。尽你所能确保程序的其余部分都不关心它。这是 KVO 实现方式的一部分。当你第一次用 KVO 观察一个对象时,它的类被切换到一个神奇的 KVO 子类,它修改了所有的访问器。一切正常,您甚至都没有注意到;但我确信调试KVO 代码本身 充其量是一种娱乐。和你的问题一样;把它记录好,否则你永远不会记得你在做什么。
      • 好的,再次感谢。看起来我的用例刚刚设置为nil,所以我可以暂时避免这种情况。
      猜你喜欢
      • 1970-01-01
      • 2015-03-23
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      • 2013-12-26
      • 2012-06-14
      • 2012-03-29
      相关资源
      最近更新 更多