Objective-C Runtime (一)

感受

淡到runtime ,讓我們先感受一下它的黑魔法,欺詐(swizz),先寫一點代碼,感受一下

  • 1.新建一個項目, SingleViewApplication 然後選擇默認的ViewController.m

  • 2.一個APP 運行的時候會先將類 load 到內存中,相當於電腦程序啓動的時候,將程序資源從硬盤放到內存中一樣

  • 3.包含頭文件 既然要使用runtime ,那就要包含頭文件 obj/runtime.h

  • 4.在 ViewController.m 文件,重寫父類方法 + (void)load

  • 5.寫下如下代碼


+ (void)load{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(my_viewWillAppear:);

        Method originalMethod = class_getInstanceMethod(class , originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class , swizzledSelector);


        BOOL didAddMethod = class_addMethod(class , originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class , swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod) );
        }else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }

    });
}
  • 6.然後重寫繼承的一個方法
    //view 即將顯示的時候調用,一般不要在這個方法中寫太多代碼,這裏用於測試
    - (void)viewWillAppear:(BOOL)animated{

        NSLog(@"viewWillAppear 哈哈");

        [super viewWillAppear:animated];
    }
  • 7.增加一個自己的方法 hehe:
    - (void)hehe:(BOOL)animated{
        NSLog(@"hehe 呵呵");
    }

好了,讓我們command + R 吧,編譯運行,輸出結果爲

這裏寫圖片描述

沒看錯,並沒有運行 * viewWillAppear:(BOOL)animated * 這裏面的代碼

讓我們在見證一下在 viewDidLoad 手動調用viewWillAppear: 這個方法

- (void)viewDidLoad {
    [super viewDidLoad];
    //手動調用
    [self viewWillAppear:YES];
}

看看運行結果

這裏寫圖片描述

結論

好像 viewWillAppear: 這個方法的代碼永遠不會被執行一樣,但是卻響應了這個消息viewWillAppear,只是執行的代碼是hehe:方法中的代碼,那麼原因是什麼?
在該類被加載到內存的時候也就是第一次 +load 的時候,使用了幾個C語言的函數,將viewWillAppear消息(消息的名字不是這個)在運行時態對應的方法,給替換了,那麼當消息循環收到這個消息的時候,就自己尋找到了對應的方法執行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章