美文网首页runtimeiOS Developerruntime runloop
SwizzlingMethod中class_addMethod方

SwizzlingMethod中class_addMethod方

作者: hecong2735 | 来源:发表于2017-06-16 13:28 被阅读283次

    一般的SwizzlingMethod实现方法:

        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            SEL originSEL = @selector(setBorderColor:);
            Method originMethod = class_getInstanceMethod([self class], originSEL);
            SEL destSEL = @selector(setBorderColorFromUIColor:);
            Method destMethod = class_getInstanceMethod([self class], destSEL);
            BOOL addSuccess = class_addMethod([self class], originSEL, method_getImplementation(destMethod), method_getTypeEncoding(destMethod));
            if (addSuccess) {
                class_replaceMethod([self class], destSEL, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
            }
            method_exchangeImplementations(originMethod, destMethod);
        });
    

    首先看下class_addMethod方法:
    class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>);
      其中四个参数分别是:要添加方法的类、方法的名字、方法的实现和方法的参数。返回一个BOOL值,如果类中已经存在该方法,则返回NO,如果类中不存在该方法,则返回YES。
    然后是class_replaceMethod方法:
    class_replaceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>)
    class_replaceMethod的执行分两种情况:
    1.类中没有被替代的方法,执行class_addMethod;
    2.类中有要被替代的方法,执行method_setImplementation

    至于为什么要先用class_addMethod方法做一次判断,是因为我们要替换的方法有可能并没有在这个类中被实现,而是在他的父类中实现的,这个时候originSEL获取到的方法就是他父类中的方法。所以我们要在当前的类中添加一个originSEL方法,但是用destSEL也就是我们自己方法的实现去实现它。然后再把父类方法的实现替换给我们自己的方法。这样就将originSELdestSEL的实现进行了交换。

    tips:
    1.SwizzlingMethod中使用dispatch_once的原因是防止有人手动调用load方法,造成交换不止进行了一次。
    2.为什么要在load方法中写SwizzlingMethod,参考SwzzlingMethod最佳实践

    相关文章

      网友评论

        本文标题:SwizzlingMethod中class_addMethod方

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