Method Swizzling

+(void)load
{

//確保線程安全原子操作,
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Class aClass = [self class];
        
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(zc_viewWillAppear:);
        
// 通過(guò)class_getInstanceMethod()函數(shù)從當(dāng)前對(duì)象中的method list獲取method結(jié)構(gòu)體,如果是類方法就使用class_getClassMethod()函數(shù)獲取。
        Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector);
        
        // When swizzling a class method, use the following:
        // Class aClass = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(aClass, originalSelector);
        // Method swizzledMethod = class_getClassMethod(aClass, swizzledSelector);
        
//添加方法
        BOOL didAddMethod =
        class_addMethod(aClass,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));
     
/** * 我們?cè)谶@里使用class_addMethod()函數(shù)對(duì)Method Swizzling做了一層驗(yàn)證,如果self沒有實(shí)現(xiàn)被交換的方法,會(huì)導(dǎo)致失敗。
    * 而且self沒有交換的方法實(shí)現(xiàn),但是父類有這個(gè)方法,這樣就會(huì)調(diào)用父類的方法,結(jié)果就不是我們想要的結(jié)果了。
    * 所以我們?cè)谶@里通過(guò)class_addMethod()的驗(yàn)證,如果self實(shí)現(xiàn)了這個(gè)方法,class_addMethod()函數(shù)將會(huì)返回NO,我們就可以對(duì)其進(jìn)行交換了。 */ 

//didAddMethod返回NO,說(shuō)明已實(shí)現(xiàn)這個(gè)方法,不需要添加,然后我們交換方法即可,否則則用原方法代理我們的swizzledMethod
        if (didAddMethod) {
            class_replaceMethod(aClass,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod); 
        }
        
        
        
        
    });
    
}

- (void)zc_viewWillAppear:(BOOL)animation
{
    NSString *str = [NSString stringWithFormat:@"%@", self.class];
    // 我們?cè)谶@里加一個(gè)判斷,將系統(tǒng)的UIViewController的對(duì)象剔除掉
    if(![str containsString:@"UI"]){
        NSLog(@"統(tǒng)計(jì)打點(diǎn) : %@", self.class);
    }

    NSLog(@"zc_viewwillAppear");
    

Method Swizzling
的實(shí)現(xiàn)原理可以理解為”方法互換“。
假設(shè)我們將A和B兩個(gè)方法進(jìn)行互換,向A方法發(fā)送消息時(shí)執(zhí)行的卻是B方法,向B方法發(fā)送消息時(shí)執(zhí)行的是A方法。
    [self zc_viewWillAppear:animation];
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 下午接到一個(gè)有趣的問(wèn)題: 看到這個(gè)問(wèn)題的第一想法就是利用runtime的方法交換,通過(guò)自己的方法替換系統(tǒng)方法,在自...
    高浩浩浩浩浩浩閱讀 539評(píng)論 0 1
  • 該文章屬于劉小壯原創(chuàng),轉(zhuǎn)載請(qǐng)注明:劉小壯[http://www.itdecent.cn/u/2de707c93d...
    劉小壯閱讀 43,854評(píng)論 141 272
  • 前言 記得《大話西游2》中有這么個(gè)橋段,紫霞仙子和豬八戒中招移魂幻影大法后靈魂互換,當(dāng)時(shí)看的也是淚流滿面。。而Me...
    01_Jack閱讀 2,320評(píng)論 7 19
  • 問(wèn)題 熟悉iOS開發(fā)的都知道,如果我們往Array或Dictionary中插入nil,應(yīng)用就會(huì)崩潰。如有下面客戶端...
    俞子將閱讀 5,292評(píng)論 10 35
  • 在 Runtime 改變selector所對(duì)應(yīng)的 imp 來(lái)達(dá)到讓原有 method 實(shí)現(xiàn)其他功能的目的 我們可以...
    不思想者Alex閱讀 2,171評(píng)論 0 3

友情鏈接更多精彩內(nèi)容