OC中load和initialize方法

前言

最近在由於工做的緣由,空餘時間相對多了一點。因此準備好好整理一下OC相關的基礎知識,以便加固相關的知識點。安全

+load方法

調用時機
  1. +load方法會在runtime加載類和分類時調用;
  2. 每一個類和分類在程序運行中只調用一次+load方法;
  3. 只要是在Compile Sources中的文件總會被加載,這與這個類是否被用到無關,所以+load方法老是在main函數以前被調用。
調用順序
  1. 執行父類的+load方法
  2. 執行當前類的+load方法
  3. 執行分類的+load方法
  4. 不一樣的類之間方法調用順序根據Compile Sources中文件的順序來 下面咱們看下實際調用狀況:
//Person.m
+ (void)load {
    NSLog(@"====== Person load function ======");
}

//Fruit.m
+ (void)load {
    NSLog(@"====== Fruit load function ======");
}

//Person子類Student
+(void)load {
    NSLog(@"======= Student load function =======");
}

//Person子類 Boy
+(void)load {
    NSLog(@"===== Boy load function =====");
}

//Person+Height分類
+(void)load {
    NSLog(@"===== Person (Height) load function =====");
}

//Person+Gender分類
+ (void)load {
    NSLog(@"======= Person (Gender) load function ========");
}
//運行結果
/*
2019-07-24 17:36:54.231549+0800 LoadDemo[10707:328172] ====== Person load function ======
2019-07-24 17:36:54.232529+0800 LoadDemo[10707:328172] ======= Student load function =======
2019-07-24 17:36:54.232701+0800 LoadDemo[10707:328172] ===== Boy load function =====
2019-07-24 17:36:54.232834+0800 LoadDemo[10707:328172] ====== Fruit load function ======
2019-07-24 17:36:54.232949+0800 LoadDemo[10707:328172] ===== Person (Height) load function =====
2019-07-24 17:36:54.233059+0800 LoadDemo[10707:328172] ======= Person (Gender) load function ========
2019-07-24 17:36:54.233225+0800 LoadDemo[10707:328172] ============== main function =========/n
*/
複製代碼

若是一個類沒有實現+load方法,那麼就不會調用它的+load方法。在Compile Sources中,文件的排放順訊就是其加載順序,也就是+load方法的調用順序。從其中也能夠看出Person+load方法調用順序優先於子類BoyStudent的順序。同時子類中+load方法的調用順序則是Compile Sources中文件的擺放順序。bash

使用場景

從上面能夠看出+load函數調用在main函數以前,同時+load方法時的環境很不安全,咱們應該儘可能減小+load方法的邏輯。另外一個緣由是+load的方法是線程安全的,它內部使用了鎖,因此咱們應當避免線程阻塞在+load方法中。 常見的使用+load方法的場景就是Method Swizzle:函數

+ (void)load {
    Method orginalFunc = class_getInstanceMethod([self class], @selector(originalFunc));
    Method swizzleFunc = class_getInstanceMethod([self class], @selector(swizzleFunc));
    method_exchangeImplementations(orginalFunc, swizzleFunc);
}
複製代碼

initialize調用

調用時機

initialize方法在第一次給某個類發送消息時調用(好比實例化一個對象),而且只會調用一次。該方法其實是一種惰性方法,也就是說若是一個類沒有被用到,那它的initialize方法就不會調用。ui

調用順序
  1. 先調用父類的initialize方法,而且即便子類沒有實現initialize方法,也會調用父類方法。
  2. 建立子類,若是子類沒有實現initialize方法,父類initialize方法會調用屢次。由於建立子類對象是要建立父類對象
  3. 有分類的類會調用分類實現的initialize方法,而不調用當前類的initialize方法。
//Person.m
+ (void)initialize {
    NSLog(@"===== Person initialize function =====");
}
//調用
 Student *student = [[Student alloc] init];

// Student中未實現initialize方法,打印結果
2019-07-25 15:20:51.585788+0800 LoadDemo[19894:580248] ===== Person initialize function =====
2019-07-25 15:20:51.585972+0800 LoadDemo[19894:580248] ===== Person initialize function =====

//Student中實現initialize方法,打印結果
2019-07-25 15:23:06.068990+0800 LoadDemo[19929:581522] ===== Person initialize function =====
2019-07-25 15:23:06.069200+0800 LoadDemo[19929:581522] ===== Student initialize function =====
複製代碼

要避免分類爲實現initialize方法,致使父類initialize方法屢次調用可使用以下方式:spa

+ (void)initialize {
    if (self == [Person class]) {
        NSLog(@"===== Person initialize function =====");
    }
}
複製代碼
使用場景

在initialize中能夠初始化一些靜態對象線程

static NSMutableArray *emptyArray;

+ (void)initialize {
    if (self == [Person class]) {
        emptyArray = [[NSMutableArray alloc] init];
        NSLog(@"===== Person initialize function =====");
    }
}
複製代碼
相關文章
相關標籤/搜索