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

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

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

E.g.

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


当前回答

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

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 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.

我觉得最大的危险是完全无意中产生许多不必要的副作用。这些副作用可能会以“bug”的形式出现,从而导致你走上错误的道路去寻找解决方案。根据我的经验,危险在于难以辨认、令人困惑和令人沮丧的代码。有点像有人在c++中过度使用函数指针。

你可能会得到一些奇怪的代码,比如

- (void)addSubview:(UIView *)view atIndex:(NSInteger)index {
    //this looks like an infinite loop but we're swizzling so default will get called
    [self addSubview:view atIndex:index];

来自实际生产代码,与一些UI魔法有关。

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.

首先,我将准确定义方法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.

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