我设置了一个类,理想情况下,它将读取传入的任何类的方法,然后在运行时将它们全部映射到单个选择器上,然后将它们转发到原始选择器。
这现在确实有效,但我一次只能为一种方法这样做。问题似乎是,一旦我切换了第一个方法,我捕获和转发该方法的IMP现在已经与其他方法IMP交换了。任何进一步的尝试都会搞砸,因为它们使用新交换的IMP来替换其他IMP。
1)所以我有MethodA、MethodB和CustomCatchAllMethod。
2)我用CustomCatchAllMEthod替换MethodA。MethodA->CustomCatchAllMethod,CustomCatchAllMethod->MethodA
3)现在我也尝试用CustomCatchAllMethod切换到MethodB,但是因为CustomCatchAllMethod now = MethodA,所以MethodB变成了MethodA和MethodA->MethodB。
那么,如何为每个要截取的新选择器获取/复制IMP的新实例呢?
以下是上述流程的粗略模型:
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:));发布于 2012-02-12 02:12:58
只有当您想要截取一个方法与另一个方法时,这种常见的方法-swizzling模式才有效。在您的例子中,您基本上是在移动catchAll:的实现,而不是将其插入到任何地方。
要正确地实现这一点,您必须使用:
IMP imp = method_getImplementation(newMethod);
method_setImplementation(origMethod, imp);然而,这给您留下了一个问题:如何前进到原始实现?
这就是原始模式使用exchangeImplementations的目的。
在您的情况下,您可以:
catchAll:构建对它们的调用。
请注意,当您希望通过相同的方法转发所有内容时,您只能处理相同大小的方法。
发布于 2014-02-26 05:28:36
您可以使用block捕获原始IMP,获取block的IMP,并将其设置为方法的实现。
Method method = class_getInstanceMethod(class, setterSelector);
SEL selector = method_getName(method);
IMP originalImp = method_getImplementation(method);
id(^block)(id self, id arg) = ^id(id self, id arg) {
return ((id(*)(id, SEL, id))originalImp)(self, selector, arg);
};
IMP newImp = imp_implementationWithBlock(block);
method_setImplementation(method, newImp);https://stackoverflow.com/questions/9242571
复制相似问题