美文网首页
iOS Runtime 方法交换

iOS Runtime 方法交换

作者: 霸_霸霸 | 来源:发表于2018-08-21 11:26 被阅读24次
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originSEL = @selector(viewWillAppear:);
        SEL swizzleSEL = @selector(xx_viewWillAppear:);
        
        Method originMethod = class_getInstanceMethod([self class], originSEL);
        Method swizzleMethod = class_getInstanceMethod([self class], swizzleSEL);
        
        /*给原来的方法添加实现
         如果添加成功则说明该类中没有实现原方法, 同时也为该原方法添加了实现(本例中的`viewWillAppear:`方法不存在这个问题)
         如果添加失败, 说明该类中已经有了原方法的实现, 直接交换方法即可
         */
        BOOL addSucceed = class_addMethod([self class], originSEL, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
        if (addSucceed) {
            //添加成功
            class_replaceMethod([self class], swizzleSEL, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        }else {
            //添加失败
            method_exchangeImplementations(originMethod, swizzleMethod);
        }
    });
}

- (void)xx_viewWillAppear:(BOOL)animated {
    //这里调用自己不会造成死循环, 看似是调用自己, 实则调用的是`viewWillAppear:`的实现
    [self xx_viewWillAppear:animated];
    NSLog(@"xx_viewWillAppear");
}
image.png
  1. 之所以选在load方法中去实现, 是因为load在文件加载的时候就会被调用, 甚至早于main函数, 这样不会出现原方法被调用的时候, 还没交换的情况

  2. dispatch_once_t就是保证这段代码只执行一次

相关文章

网友评论

      本文标题:iOS Runtime 方法交换

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