复制多个方法swizzles的方法IMP [英] Copy a method IMP for multiple method swizzles
问题描述
我有一个类设置,理想情况下会读取传入的任何类的方法,然后在运行时将它们全部映射到单个选择器上,然后将它们转发到原始选择器。
I have a class set up that ideally will read the methods of any class passed in and then map all of them to on single selector at runtime before forwarding them off to their original selector.
这现在可以正常工作,但我一次只能使用一种方法。问题似乎是,一旦我调整第一个方法,我的IMP捕获和转发方法现在已经与其他方法IMP交换。由于他们使用新交换的IMP替换其他IMP,所以进一步尝试这个搞砸了。
This does work right now, but I can only do it for one method at a time. The issue seems to be that once I swizzle the first method, my IMP to catch and forward the method has now been swapped with that other methods IMP. Any further attempts at this screw up because they use newly swapped IMP to replace the others.
1)所以我有MethodA,MethodB和CustomCatchAllMethod。
1)So I have MethodA, MethodB, and CustomCatchAllMethod.
2)我将MethodA与CustomCatchAllMEthod交换。 MethodA-> CustomCatchAllMethod,CustomCatchAllMethod-> MethodA
2)I swap MethodA with CustomCatchAllMEthod. MethodA->CustomCatchAllMethod, CustomCatchAllMethod->MethodA
3)现在我尝试使用CustomCatchAllMethod交换到MethodB,但由于CustomCatchAllMethod现在= MethodA,因此MethodB成为MethodA和MethodA - > MethodB。
3)Now I try to swap to MethodB with CustomCatchAllMethod as well, but since CustomCatchAllMethod now = MethodA, MethodB becomes MethodA and MethodA->MethodB.
那么如何为每个我想截取的新选择器获取/复制IMP的新实例?
So how do I get/copy a new instance of my IMP for each new selector I want to intercept?
以下是上述流程的粗略模型:
Here's a rough mockup of the above flow:
void swizzle(Class classImCopying, SEL orig){
SEL new = @selector(catchAll:);
Method origMethod = class_getInstanceMethod(classImCopying, orig);
Method newMethod = class_getInstanceMethod(catchAllClass,new);
method_exchangeImplementations(origMethod, newMethod);
}
//In some method elsewhere
//I want this to make both methodA and methodB point to catchAll:
swizzle(someClass, @selector(methodA:));
swizzle(someClass, @selector(methodB:));
推荐答案
这种常见的方法 - 混合模式只在你想要的时候有效用一个方法拦截一种方法。在你的情况下,你基本上是移动 catchAll:
的实现而不是在任何地方插入它。
That common method-swizzling pattern only works when you want to intercept one method with one other. In your case you are basically moving the implementation for catchAll:
around instead of inserting it everywhere.
要正确到你必须使用:
IMP imp = method_getImplementation(newMethod);
method_setImplementation(origMethod, imp);
这会给你留下一个问题:如何转发到原始实现?
这就是原始模式使用 exchangeImplementations
for。
This leaves you with one problem though: how to forward to the original implementation?
That is what the original pattern used exchangeImplementations
for.
在你的情况下你可以:
- 保留一张原始
IMP
的表格或 - 使用一些公共前缀重命名原始方法,因此您可以从
catchAll:
- keep a table of the original
IMP
s around or - rename the original methods with some common prefix, so you can build a call to them from
catchAll:
请注意,当您想通过相同的方法转发所有方法时,您只能处理相同的方法。
Note that you can only handle methods of the same arity when you want to forward everything through the same method.
这篇关于复制多个方法swizzles的方法IMP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!