当使用自由函数(也称为常规函数)进行调配时,您需要考虑Objective-C
编译器为您想要调配的方法生成的实际方法签名,以及它只是一个函数指针的事实IMP
,声明如下:
typedef id (*IMP)(id, SEL, ...);
假设您有一个名为 的方法doSomethingWithObject:afterDelay:
,它看起来像这样
- (void)doSomethingWithObject:(id)object afterDelay:(NSTimeInterval)delay
编译器生成的相应 C 函数是(有关名称修改的更多信息,请参见WikipediaObjective-C
):
void _i_MyClass_doSometingWithObject_afterDelay(id self, SEL _cmd, id object, NSTimeInterval delay)
所以如果你想交换它,你需要创建一个类似的方法并将指针传递给它:
void swizzledDoSometingWithObjectAfterDelay(id self, SEL _cmd, id object, NSTimeInterval delay) {
// custom implementation
}
// ....
method_setImplementation(method, (IMP)swizzledDoSometingWithObjectAfterDelay);
如果您想要调配的方法可能在祖先类中声明,并且您只想为您感兴趣的子类调配它,则可以使用class_replaceMethod(),它可以添加或替换该方法,并且仅影响目标类:
SEL selector = @selector(doSomethingWithObject:afterDelay:);
IMP newImp = (IMP)swizzledDoSometingWithObjectAfterDelay
Method method = class_getClassMethod([MyClass class], selector);
const char * encoding = method_getTypeEncoding(method);
class_replaceMethod([MyClass class], selector, newIMP, encoding)