Objective-C Runtime (二)

前篇的代碼已經讓我們感受到了runtime的詭異,現在讓我們分析幾行代碼


//1.載入內存的時候調用
+ (void)load{

    /*2.單例代碼塊,保證代碼塊中的代碼只運行一次*/
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        /*3.得到描述一個類的結構體地址 typedef struct*/ objc_class *Class
        Class class = [self class];

        /*4.得到兩個 sel 其實就是函數指針入口,但是我感覺這裏像是消息,就是一個標記(字符串),其值在一個類的結構描述中,是唯一的 */
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(hehe:);

        /*5.得到實現方法的實例 地址 也就是存放在 這個class objc_method_list 方法列表中的地址,這裏想當然 用 class 這個地址 加 標示地址,的地址*/
        Method originalMethod = class_getInstanceMethod(class , originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class , swizzledSelector);

        /*6.將一個方法添加到這個類的objc_method_list 也就是註冊,SEL 是發送的消息,也就是objc_msgSend(object, @selector(message)); 試想一下 SEL 就是一個字符串,也就是 key, 那麼 value 就是 swizzledMethod 執行的地址*/

        /* 添加到
            6.1.class (描述類的結構體首地址),

            6.2.SEL 表示唯一標示,

            6.3.IMP :函數指針,實現消息的方法, method_getImplementation(swizzledMethod) 是實現 swizzledMethod 這個方法的地址

            6.4.const char * 相信大家對  int main(int argc, char * argv[]) 這個都清楚吧, 描述參數 和返回值 類型
         */

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

        /*7 如果添加成功,那麼就替換自身的消息,hehe:YES 就會執行 系統的 viewWillAppear*/
        if (didAddMethod) {
            class_replaceMethod(class , swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod) );

        /*8.如果添加沒成功,那麼就交換兩個實現方法*/
        }else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }

    });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章