我正在尝试使用 SIMBL 修改程序的行为(我没有它的源代码)。我使用了类转储,发现我需要覆盖一个实例方法
此方法在称为控制器的类中。我需要做的就是获取参数 arg1 就可以了。也许 NSLog 它或发布通知...我阅读了有关在 Objective-C 中调配的方法,但我该如何使用它?我需要参考我没有课程的 MessageController 类。
谢谢!
我正在尝试使用 SIMBL 修改程序的行为(我没有它的源代码)。我使用了类转储,发现我需要覆盖一个实例方法
此方法在称为控制器的类中。我需要做的就是获取参数 arg1 就可以了。也许 NSLog 它或发布通知...我阅读了有关在 Objective-C 中调配的方法,但我该如何使用它?我需要参考我没有课程的 MessageController 类。
谢谢!
我猜你需要在完成 NSLog 之后调用原始实现;如果没有,您可以只使用类上的类别来覆盖该方法。
要调配方法,首先您需要一个替换方法。我通常把这样的东西放在目标类的一个类别中:
- (void)replacementReceiveMessage:(const struct BInstantMessage *)arg1 {
NSLog(@"arg1 is %@", arg1);
[self replacementReceiveMessage:arg1];
}
看起来它会递归地调用自己,但它不会因为我们要交换东西所以调用ReceiveMessage:
调用这个方法,而调用replacementReceiveMessage:
调用旧版本。
第二步是使用运行时函数来实际执行交换。使用类别的好处是可以load
在类别中使用来完成工作:
+ (void)load {
SEL originalSelector = @selector(ReceiveMessage:);
SEL overrideSelector = @selector(replacementReceiveMessage:);
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method overrideMethod = class_getInstanceMethod(self, overrideSelector);
if (class_addMethod(self, originalSelector, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
class_replaceMethod(self, overrideSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, overrideMethod);
}
}
有两种情况需要处理:
class_addMethod
向目标类添加一个实现ReceiveMessage:
,我们使用我们的替换实现来做到这一点。然后我们可以用超类的实现class_replaceMethod
来替换replacementReceiveMessage:
,这样我们的新版本就能正确调用旧的了。class_addMethod
将失败,但我们可以使用method_exchangeImplementations
只是交换新旧版本。图书馆jrswizzle处理它。不建议自己做,因为有很多细节要做好。(请参阅 jrswizzle 自述文件中记录先前实现失败的表格。)
假设您有这样的课程:
@interface Weh : NSObject
-(void)foo;
-(void)bar;
@end
@implementation Weh
-(void)foo {
NSLog(@"Foo called");
}
-(void)bar {
NSLog(@"Bar called");
[self bar];
}
@end
你可以像这样使用它:
Weh *weh = Weh.new;
[weh foo];
[Weh jr_swizzleMethod:@selector(foo) withMethod:@selector(bar) error:nil];
[weh foo];
输出:
Foo called
Bar called
Foo called