美文网首页
class_addMethod和class_replaceMet

class_addMethod和class_replaceMet

作者: 笑破天 | 来源:发表于2022-08-07 21:23 被阅读0次

runtime中方法交换的经典代码如下,其中的class_addMethod和class_replaceMethod怎么理解?

/*
     周全起见,有两种情况要考虑一下
     第一种情况:要交换的方法并没有在目标类中实现,而是在其父类中实现了, 这时使用class_getInstanceMethod函数获取到的originalSelector指向的就是父类的方法
     第二种情况:要交换的方法已经存在于目标类中
*/
    BOOL didAdd = class_addMethod(class, oldSel, method_getImplementation(newM), method_getTypeEncoding(newM));
    if (didAdd) {
        NSLog(@"swizzleInstanceSel * didAdd");
        class_replaceMethod(class, newSel, method_getImplementation(oldM), method_getTypeEncoding(oldM));
    }
    else {
        NSLog(@"swizzleInstanceSel * didn'tAdd ----> exchange!");
        method_exchangeImplementations(oldM, newM);
    }

疑惑:iOS中存在一个方法子类中有父类中没有的case吗?

1、class_addMethod 添加方法

+ (void)load
{
    Method method = class_getInstanceMethod([self class], @selector(sayHello));
  //添加一个方法personSayHello, 它的实现指向sayHello的实现
    BOOL res = class_addMethod([self class], @selector(personSayHello), method_getImplementation(method), method_getTypeEncoding(method));
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(personSayHello)];
}

- (void)sayHello
{
    NSLog(@"say hello");
}
//打印say hello

总结:添加一个方法personSayHello, 它的实现指向sayHello的实现,若目标类已存在该方法的实现就返回NO,什么也不做,若不存在就add一个,相当于一次method_setImplementation。若直接调用personSayHello方法,会报错unrecognized selector sent to instance

2、class_replaceMethod 替换方法

+ (void)load
{
    Method method = class_getInstanceMethod([self class], @selector(sayGoodBye));
    class_replaceMethod([self class], @selector(sayHello), method_getImplementation(method), method_getTypeEncoding(method));
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(sayHello)];
    [self performSelector:@selector(sayGoodBye)];
}

- (void)sayHello
{
    NSLog(@"say hello");
}

- (void)sayGoodBye
{
    NSLog(@"say goodbye");
}
//打印say goodbye、say goodbye

总结:目标类中该方法,不存在时就add,相当于class_addMethod,存在时就replace,相当于method_setImplementation。返回值表示之前的方法实现。

3、method_exchangeImplementations 交换方法

+ (void)load
{
    Method sayGoodsByeMethod = class_getInstanceMethod([self class], @selector(sayGoodBye));
    Method sayHelloMethod = class_getInstanceMethod([self class], @selector(sayHello));
    method_exchangeImplementations(sayHelloMethod, sayGoodsByeMethod);
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(sayHello)];
    [self performSelector:@selector(sayGoodBye)];
}

- (void)sayHello
{
    NSLog(@"say hello");
}

- (void)sayGoodBye
{
    NSLog(@"say goodbye");
}
//打印say goodbye、say hello

总结:相当于调用2次method_setImplementation,俩方法中任意一个方法没有实现都会报错。

总结

回到开始看代码逻辑:当方法不存在,就add再replace,存在就exchange,都是调2次method_setImplementation。

参考:
class_addMethod、class_replaceMethod
iOS中的HOOK技术
class_addMethod实解

相关文章

网友评论

      本文标题:class_addMethod和class_replaceMet

      本文链接:https://www.haomeiwen.com/subject/furiwrtx.html