在Objective-C中方法混乱的正确方法 [英] Proper way of method swizzling in objective-C
问题描述
当前在Objective-C中使用方法swizzling
进行实验,我有一个问题.我试图了解解决方法的正确方法,并且在网上研究后偶然发现了NSHipster的这一帖子:
http://nshipster.com/method-swizzling/
Currently experimenting with method swizzling
in Objective-C and I have a question. I am trying to understand the proper way to method swizzle and after researching online I stumbled upon this NSHipster post:
http://nshipster.com/method-swizzling/
在帖子中,作者提供了一些使示例代码混乱的方法.我正在寻找可以更好地向我解释作者正在做什么的人.尤其是我对didAddMethod
逻辑感到困惑.为什么作者不仅仅直接使用swapping/exchanging
方法实现?我对此的唯一理论是,也许还没有机会将viewWillAppear:
尚未添加到UIViewController's method
dispatch_table
中.特别是如果类别可能先在UIViewController
之前加载到内存中,这就是原因吗?似乎很奇怪?只是希望获得更多的见解/澄清,谢谢:)
In the post the author has some method swizzling sample code. I am looking for someone to better explain to me what the author is doing.. In particular I am confused on the didAddMethod
logic. Why is the author not just directly swapping/exchanging
method implementations? My only theory on this is maybe there is some off chance that viewWillAppear:
is not added to UIViewController's method
dispatch_table
yet. Particularly if maybe the category is loaded into memory first before UIViewController
... Is this the reason why? It seems rather odd? Just looking for some more insight/clarity, thanks :)
推荐答案
尤其是我对didAddMethod逻辑感到困惑.为什么作者不只是直接交换/交换方法实现?
In particular I am confused on the didAddMethod logic. Why is the author not just directly swapping/exchanging method implementations?
您的困惑是可以理解的,因为这种逻辑没有得到清楚的解释.
Your confusion is understandable as this logic is not explained clearly.
首先忽略以下事实:该示例是特定类UIViewController
上的类别,而只是考虑逻辑,就好像该类别位于某个任意类上一样,我们将该类称为TargetClass
.
First ignore the fact that the example is a category on the specific class UIViewController
and just consider the logic as though the category was on some arbitrary class, let's call that class TargetClass
.
我们将调用要替换的现有方法existingMethod
.
We'll call the existing method we wish to replace existingMethod
.
位于TargetClass
上的类别将TargetClass
.
重要:请注意,获取方法class_getInstanceMethod
的函数将在提供的类或其任何超类中找到该方法.但是,功能class_addMethod
和class_replaceMethod
仅在提供的类中添加/替换方法.
Important: Note that the function to get an method, class_getInstanceMethod
, will find the method in the supplied class or any of its superclasses. However the functions class_addMethod
and class_replaceMethod
only add/replace methods in the supplied class.
现在有两种情况需要考虑:
Now there are two cases to consider:
-
TargetClass
本身直接包含existingMethod
的实现.这是简单的情况,所有要做的就是交换existingMethod
和swizzlingMethod
的实现,可以用method_exchangeImplementations
完成.在本文中,对class_addMethod
的调用将失败,因为直接在TargetClass
中的existingMethod
已经存在,并且逻辑导致对method_exchangeImplementations
的调用.
TargetClass
itself directly contains an implementation ofexistingMethod
. This is the easy case, all that needs to be done is exchange the implementations ofexistingMethod
andswizzlingMethod
, which can be done withmethod_exchangeImplementations
. In the article the call toclass_addMethod
will fail, as there is already andexistingMethod
directly inTargetClass
and the logic results in a call tomethod_exchangeImplementations
.
TargetClass
并没有不直接包含existingMethod
的实现,而是通过继承自TargetClass
的祖先类之一提供了该方法.这是比较棘手的情况.如果仅交换existingMethod
和swizzlingMethod
的实现,那么您将影响祖先类(的实例)(并且可能会导致崩溃的原因-为什么不做练习).通过调用class_addMethod
,本文的代码可确保TargetClass
中有一个existingMethod
-其实现是swizzlingMethod
的原始实现.然后,逻辑将swizzlingMethod
的实现替换为祖先的existingMethod
的实现(对祖先没有影响).
TargetClass
does not directly contain an implementation of existingMethod
, rather that method is provided through inheritance from one of the ancestor classes of TargetClass
. This is the trickier case. If you simply exchange the implementations of existingMethod
and swizzlingMethod
then you would be effecting (instances of) the ancestor class (and in a way which could cause a crash - why is left as an exercise). By calling class_addMethod
the article's code makes sure there is an existingMethod
in TargetClass
- the implementation of which is the original implementation of swizzlingMethod
. The logic then replaces the implementation of swizzlingMethod
with the implementation of the ancestor's existingMethod
(which has no effect on the ancestor).
还在这里吗?我希望这是有道理的,而不仅仅是让您眼花!乱!
Still here? I hope that makes sense and hasn't simply sent you cross-eyed!
如果您终极好奇,请执行另一个练习:现在您可能会问,如果祖先的existingMethod
实现包含对super
的调用,会发生什么情况……如果该实现现在也已附加到TargetClass
中的swizzlingMethod
对super
的调用将在哪里结束?是在祖先的实现中执行相同的方法实现两次,还是在祖先的祖先中实现了原来的意图?
Another exercise if you're terminally curious: Now you might ask what happens if the ancestor's existingMethod
implementation contains a call to super
... if the implementation is now also attached to swizzlingMethod
in TargetClass
where will that call to super
end up? Will it be to implementation in ancestor, which would see the same method implementation executed twice, or to the ancestor's ancestor, as originally intended?
HTH
这篇关于在Objective-C中方法混乱的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!