我曾听人说过,这种方法是一种危险的做法。就连“swizzling”这个名字也暗示着这是一种欺骗。

方法Swizzling正在修改映射,以便调用选择器A将实际调用实现b。这样做的一个用途是扩展闭源类的行为。

我们是否可以将风险正式化,以便决定是否使用swizzling的人可以做出明智的决定,是否值得他们尝试这样做。

E.g.

命名冲突:如果类后来扩展其功能以包含您添加的方法名,将会导致大量的问题。通过合理地命名swizzled方法来降低风险。


当前回答

谨慎而明智地使用它,可以得到优雅的代码,但通常情况下,它只会导致令人困惑的代码。

我认为应该禁止它,除非您碰巧知道它为特定的设计任务提供了非常好的机会,但您需要清楚地知道为什么它很适合这种情况,以及为什么替代方案不能很好地适用于这种情况。

例如,方法swizzling的一个很好的应用是isa swizzling,这就是ObjC实现键值观察的方式。

一个糟糕的例子可能是依赖于方法变换作为扩展类的一种手段,这会导致极高的耦合。

其他回答

首先,我将准确定义方法swizzling的含义:

将最初发送到方法(称为a)的所有调用重新路由到新方法(称为B)。 我们拥有方法B 我们没有A方法 方法B做了一些工作,然后调用方法A。

方法搅拌比这更普遍,但这是我感兴趣的情况。

危险:

Changes in the original class. We dont own the class that we are swizzling. If the class changes our swizzle may stop working. Hard to maintain. Not only have you got to write and maintain the swizzled method. you have to write and maintain the code that preforms the swizzle Hard to debug. It is hard to follow the flow of a swizzle, some people may not even realise the swizzle has been preformed. If there are bugs introduced from the swizzle (perhaps dues to changes in the original class) they will be hard to resolve.

总之,您应该将混合保持在最低限度,并考虑原始类的更改可能如何影响您的混合。此外,你应该清楚地评论和记录你正在做的事情(或者完全避免它)。

谨慎而明智地使用它,可以得到优雅的代码,但通常情况下,它只会导致令人困惑的代码。

我认为应该禁止它,除非您碰巧知道它为特定的设计任务提供了非常好的机会,但您需要清楚地知道为什么它很适合这种情况,以及为什么替代方案不能很好地适用于这种情况。

例如,方法swizzling的一个很好的应用是isa swizzling,这就是ObjC实现键值观察的方式。

一个糟糕的例子可能是依赖于方法变换作为扩展类的一种手段,这会导致极高的耦合。

虽然我使用了这种技巧,但我想指出:

It obfuscates your code because it can cause un-documented, though desired, side effects. When one reads the code he/she may be unaware of the side effect behavior that is required unless he/she remembers to search the code base to see if it has been swizzled. I'm not sure how to alleviate this problem because it is not always possible to document every place where the code is dependent upon the side effect swizzled behavior. It can make your code less reusable because someone who finds a segment of code which depends upon the swizzled behavior that they would like to use elsewhere cannot simply cut and paste it into some other code base without also finding and copying the swizzled method.

It's not the swizzling itself that's really dangerous. The problem is, as you say, that it's often used to modify the behavior of framework classes. It's assuming that you know something about how those private classes work that's "dangerous." Even if your modifications work today, there's always a chance that Apple will change the class in the future and cause your modification to break. Also, if many different apps do it, it makes it that much harder for Apple to change the framework without breaking a lot of existing software.

方法变换在单元测试中非常有用。

它允许您编写一个模拟对象,并使用该模拟对象而不是实际对象。代码保持干净,单元测试具有可预测的行为。假设您想要测试一些使用CLLocationManager的代码。你的单元测试可以混合startUpdatingLocation,这样它就会给你的委托提供一组预定的位置,而你的代码就不必改变了。