在Objective-C中方法混乱的正确方法 [英] Proper way of method swizzling in objective-C

查看:127
本文介绍了在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_addMethodclass_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:

  1. TargetClass本身直接包含existingMethod的实现.这是简单的情况,所有要做的就是交换existingMethodswizzlingMethod的实现,可以用method_exchangeImplementations完成.在本文中,对class_addMethod的调用将失败,因为直接在 TargetClass中的existingMethod 已经存在,并且逻辑导致对method_exchangeImplementations的调用.

  1. TargetClass itself directly contains an implementation of existingMethod. This is the easy case, all that needs to be done is exchange the implementations of existingMethod and swizzlingMethod, which can be done with method_exchangeImplementations. In the article the call to class_addMethod will fail, as there is already and existingMethod directly in TargetClass and the logic results in a call to method_exchangeImplementations.

TargetClass并没有直接包含existingMethod的实现,而是通过继承自TargetClass的祖先类之一提供了该方法.这是比较棘手的情况.如果仅交换existingMethodswizzlingMethod的实现,那么您将影响祖先类(的实例)(并且可能会导致崩溃的原因-为什么不做练习).通过调用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中的swizzlingMethodsuper的调用将在哪里结束?是在祖先的实现中执行相同的方法实现两次,还是在祖先的祖先中实现了原来的意图?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆