天天看點

你真的懂使用Runtime進行swizzle的最佳寫法?

前言

runtime 的黑魔法很多人都一定聽過,或者已經在使用了。但是,怎麼swizzle方法才是最好呢?

一般寫法

Method originalMethod = class_getInstanceMethod(aClass, originalSel);
    Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
    method_exchangeImplementations(originalMethod, swizzleMethod);
           

或者是下面這種方式,swizzle第二種寫法:

Method originalMethod = class_getInstanceMethod(aClass, originalSel);
    Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
    BOOL didAddMethod = class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
    if (didAddMethod) {
        class_replaceMethod(aClass, swizzleSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    }else{
        method_exchangeImplementations(originalMethod, swizzleMethod);
    }
           

更好寫法

其它,這樣寫,一般不會有問題,但是在一些情況下,比如這個hook的類沒有實作你要swizzle的方法,這時是沒有swizzle成功的,然後你自己寫的 swizzle 裡又自己調用自己,就無限循環。

Method originalInsMethod = class_getInstanceMethod(class, originalSelector);
    // 處理為執行個體方法
    if (originalInsMethod)
    {
        method_exchangeImplementations(originalInsMethod, swizzledMethod);
    }else{
        // 處理為類方法
        Method originalClassMethod = class_getClassMethod(class, originalSelector);
        if (originalClassMethod)
        {
            method_exchangeImplementations(originalClassMethod, swizzledMethod);
        }else{
            // 如果hook的類沒有實作這個方法,則先添加方法,然後設定方法的IMP為一個空block。否則直接class_replaceMethod,則方法實則沒有交接
            class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            method_setImplementation(swizzledMethod, imp_implementationWithBlock(^(id self, SEL _cmd){}));
        }
    }
           

總結

至于這個為什麼會更好? 有時間在慢慢說啦~

參考

注:本文首發于 iHTCboy's blog ,如若轉載,請注明來源。

繼續閱讀