Мне нужно заменить некоторые методы реализации конкретных классов Objective-C. Набор функций из библиотеки objc/runtime способен это сделать. Чтобы упростить этот вопрос, я просто написать простейший пример кода следующим образом:Почему ARC вызывает EXC_BAD_ACCESS при выполнении swizzling-функций с использованием class_replaceMethod из библиотеки времени выполнения objc?
#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-дуга устанавливается, этот код работает отлично:
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-дуги). Сигнал EXC_BAD_ACCESS вызывается при вызове gOriginalFunc (как говорят комментарии). Я не знаю причины, может ли кто-нибудь сказать?
Примечание: «крюк» = "swizzling" in objc parlance – justin