首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现方法swizzling?

如何实现方法swizzling?
EN

Stack Overflow用户
提问于 2011-03-21 05:23:47
回答 2查看 12.7K关注 0票数 9

我正在尝试使用SIMBL修改一个程序的行为(我没有它的源代码)。我使用了类转储,发现我需要重写一个实例方法

此方法位于名为controller的类中。我所需要做的就是得到参数arg1,就这样了。也许NSLog它或张贴一个通知...我在objective-c中读到过有关方法的文章,但是我该如何使用它呢?我需要参考MessageController这门课,我没有这门课。

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-21 06:38:26

我猜您需要在执行NSLog之后调用原始实现;如果不是这样,您可以只使用类上的一个类别来覆盖该方法。

要使用该方法,首先需要一个替换方法。我通常会在目标类的类别中放一些类似的东西:

代码语言:javascript
复制
- (void)replacementReceiveMessage:(const struct BInstantMessage *)arg1 {
    NSLog(@"arg1 is %@", arg1);
    [self replacementReceiveMessage:arg1];
}

这看起来像是它会递归地调用自己,但它不会,因为我们要交换东西,所以在调用replacementReceiveMessage:时,调用ReceiveMessage:调用这个方法,同时调用旧版本。

第二步是使用运行时函数实际执行交换。使用类别的好处是,您可以在类别中使用load来完成工作:

代码语言:javascript
复制
+ (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_addMethodReceiveMessage:的实现添加到目标类中,这是我们使用替换实现所做的。然后我们可以使用class_replaceMethodreplacementReceiveMessage:替换为超类的实现,这样我们的新版本将能够正确地调用旧的。
  • 如果该方法是在目标类中定义的,class_addMethod将失败,但然后我们可以使用method_exchangeImplementations来交换新旧版本。
票数 35
EN

Stack Overflow用户

发布于 2013-07-03 03:42:40

jrswizzle处理它。不推荐自己做,因为有很多细节需要正确处理。(请参阅jrswizzle自述文件中记录以前实现失败的表格。)

假设你有这样的类:

代码语言:javascript
复制
@interface Weh : NSObject
-(void)foo;
-(void)bar;
@end

@implementation Weh
-(void)foo {
    NSLog(@"Foo called");
}
-(void)bar {
    NSLog(@"Bar called");
    [self bar];
}
@end

你可以这样使用它:

代码语言:javascript
复制
Weh *weh = Weh.new;
[weh foo];
[Weh jr_swizzleMethod:@selector(foo) withMethod:@selector(bar) error:nil];
[weh foo]; 

输出:

代码语言:javascript
复制
Foo called
Bar called
Foo called
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5371601

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档