目前在Objective-C中尝试使用方法swizzling
,我有一个问题。我试图理解方法混合的正确方法,在网上研究后我偶然发现了这个NSHipster帖子:
http://nshipster.com/method-swizzling/
在帖子中,作者有一些方法调整样本代码。我正在寻找一个能够更好地向我解释作者正在做什么的人。特别是我对didAddMethod
逻辑感到困惑。为什么作者不仅仅是直接swapping/exchanging
方法实现?我唯一的理论是,viewWillAppear:
UIViewController's method
尚未添加dispatch_table
。特别是如果类别在UIViewController
之前首先被加载到内存中......这是为什么?看起来很奇怪?只是寻找更多洞察力/清晰度,谢谢:))
答案 0 :(得分:6)
特别是我对didAddMethod逻辑感到困惑。为什么作者不只是直接交换/交换方法实现?
你的困惑是可以理解的,因为这个逻辑没有得到清楚的解释。
首先忽略一个事实,即该示例是特定类UIViewController
上的一个类别,并且只考虑逻辑,好像该类别在某个任意类上,让我们调用该类TargetClass
我们会调用我们希望替换existingMethod
的现有方法。
TargetClass
上的类别将我们称之为swizzlingMethod
的混合方法添加到TargetClass
。
重要:请注意,获取方法class_getInstanceMethod
的函数将在提供的类或其任何超类中找到该方法。但是,函数class_addMethod
和class_replaceMethod
仅在提供的类中添加/替换方法。
现在有两种情况需要考虑:
TargetClass
本身直接包含existingMethod
的实现。这是一个简单的案例,所有需要做的就是交换existingMethod
和swizzlingMethod
的实现,这可以通过method_exchangeImplementations
完成。在文章中,对class_addMethod
的调用将失败,因为已经existingMethod
直接在 TargetClass
中,逻辑会导致调用method_exchangeImplementations
}。
TargetClass
不直接包含existingMethod
的实现,而是通过从TargetClass
的祖先类之一继承来提供该方法。这是一个棘手的案例。如果您只是简单地交换existingMethod
和swizzlingMethod
的实现,那么您将影响祖先类的(实例)(并且可能导致崩溃 - 为什么留下作为练习)。通过调用class_addMethod
文章的代码可确保existingMethod
中有TargetClass
- 其实施是swizzlingMethod
的原始实现。然后,逻辑将swizzlingMethod
的实现替换为祖先existingMethod
的实现(对祖先没有影响)。
还在吗?我希望这是有道理的,并没有简单地发送你的眼睛!
如果你最后好奇的另一个练习:现在你可能会问,如果祖先的existingMethod
实现包含对super
的调用,会发生什么......如果现在实现的话还附加到swizzlingMethod
TargetClass
super
,pio-stop-all
号召唤到哪里?它是在祖先中执行,它会看到相同的方法实现执行两次,还是原始的祖先的祖先?
HTH
答案 1 :(得分:0)
M(1,3,0.9
时会调用 load
。
因此,假设在obj-c运行时中添加了class
,它已经包含UIViewController
,但您希望它被另一个实现替换。首先,您添加一个新方法viewWillAppear:
。
现在,xxxWillAppear:
课程中添加xxxWillAppear:
后,您才可以替换它。
但作者也说:
例如,假设我们想要跟踪每个视图控制器在iOS应用中向用户呈现的次数
所以他试图演示一个应用可能有很多视图控制器但你不想继续替换每个ViewController
ViewController
实现的情况。一旦viewWillAppear:
的点被替换,则不需要添加,只需要进行交换。
也许Objective C运行时的源代码可能会有所帮助:
viewWillAppear:
如果你愿意,你可以挖掘更多: