我需要替换某些特定Objective-C类的方法实现。 objc / runtime库中的一组函数能够做到这一点。为简化问题,我只需编写如下最简单的示例代码:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface MyClass : NSObject
- (void) func;
@end
@implementation MyClass
- (void) func {
NSLog(@"Hello from MyClass!");
}
@end
//Original implementation of the method
static IMP gOriginalFunc = nil;
//Hook function that will take place of the original method
void HookFunc(id self, SEL _cmd)
{
NSLog(@"[MyClass func] is hooked!");
gOriginalFunc(self, _cmd);//EXC_BAD_ACCESS occurs here when ARC is enabled!!
}
int main(int argc, char *argv[])
{
Class clsMyClass = objc_getClass("MyClass");
// Restore the original method implementation:
gOriginalFunc = class_getMethodImplementation(clsMyClass, @selector(func));
Method mtdFunc = class_getInstanceMethod(clsMyClass, @selector(func));
// Replace implementaion of the method of my own:
class_replaceMethod(clsMyClass, @selector(func), IMP(HookFunc), method_getTypeEncoding(mtdFunc));
objc_registerClassPair(clsMyClass);
MyClass* obj = [[MyClass alloc] init];
[obj func];
return 0;
}
我只是替换[MyClass func]的原始实现。当设置编译器标志-fno-objc-arc时,此代码可以正常工作:
2014-12-18 11:59:17.524 Hooker[749:72783] [MyClass func] is hooked!
2014-12-18 11:59:20.361 Hooker[749:72783] Hello from MyClass!
但是启用ARC时会出现问题(通过将编译器标志设置为-fobjc-arc)。调用gOriginalFunc时抛出EXC_BAD_ACCESS信号(如注释所示)。我不知道原因,谁能说出来?
答案 0 :(得分:1)
您的函数原型不准确,编译器错误地设置了调用。使用ARC,包括引用计数操作。要么是未定义的行为。
要更正程序,请通知编译器实际的功能签名,以免它搞砸了电话:
typedef void (*HookFunc_Signature)(id, SEL); // << != IMP's signature
static HookFunc_Signature gOriginalFunc = nil;
...后:
gOriginalFunc = (HookFunc_Signature)class_getMethodImplementation(clsMyClass, @selector(func));