NSObject的Initialize與Load方法

1、Initialize類方法html

在類收到第一條消息前調用initialize類方法(lazy,這一點和Java類的「clinit」的很像)。ios

一、在項目期只執行一次或者不執行,其它線程都會被阻塞等initialize方法執行完畢。安全

二、在類收到第一次消息以前調用,根據繼承體系由上至下依次實例化類,父類先於子類執行initialize方法(若是父類或當前類已執行過initialize,就再也不執行)。若是子類沒有重寫initialize類方法,就繼承父類的initialize類方法。函數

三、若是子類和多個分類同時重寫initialize類方法,只會執行某一個分類中的initialize類方法。ui

四、禁止在重寫中加入[super initialize]。spa

五、本着每一個類的initialize只執行一次,且確定會被執行。須要排除如下違反原則的場景:子類及子類的分類沒有重寫Initialize方法,或者重寫Initialize方法時加入[super initialize],這兩種場景會致使父類的Initialize類方法被重複執行;類及類的分類重寫initialize方法,致使哪個被調用是不肯定的。線程

綜上,正確的寫法應該是,不在分類中重寫,重寫時按照以下方式:code

+ (void)initialize {
    if (self == [ClassName self]) {
    // ... do the initialization ...
  }
}

六、因爲initialize運行時會加鎖,避免死鎖或沒必要要的內存浪費,方法內需減小沒必要要代碼。通常加入代碼是給在編譯期沒法初始化的全局變量和靜態變量賦值,如給orm

static NSMutableArray *mutableArray的mutableArray複製等等。htm

+ (void)initialize
{
    if (self == [ClassName class]) {
        mutableArray = [[NSMutableArray alloc] init];
        recursiveLock = [[NSRecursiveLock alloc] init];
        myLock = [[NSLock alloc] init];
        error = [[NSError alloc] initWithDomain:NetworkRequestErrorDomain code:ASIRequestTimedOutErrorType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The request timed out",NSLocalizedDescriptionKey,nil]];  
        operationQueue = [[NSOperationQueue alloc] init];
        [operationQueue setMaxConcurrentOperationCount:4];
    }
}

 

 


在initialize方法收到調用時,運行環境基本健全。
initialize的運行過程當中是能保證線程安全的。
和load不一樣,

 

2、Load方法

只要在Target>>Build Phases>>Compile Sources中存在的類,類中也重寫了load方法,會在App啓動時(main函數前)進行加載。

一、父類、子類、分類中的load方法都會被執行,執行順序:先是父類,再是子類,分類的執行順序跟CompileSources中順序一致。

二、若是子類沒有重寫load方法,不會繼承父類的load方法,致使父類的load被2次調用。沒有load方法實現就不會調用,不會考慮對NSObject的繼承。

三、禁止重寫load時加入[super load]。

四、在有依賴關係的兩個庫中,被依賴的類的load會優先調用。但在一個庫以內,調用順序是不肯定的,所以在load方法中不能加入建立同庫其它類的實例的方法,通常在方法中加入Method Swizzle。

 

3、依賴環

若是在A類的initialize方法中,對B類的對象調用方法,同時在B類的initialize方法裏,加入對A類的對象調用方法,就會致使出現依賴環。

 

4、參考

NSObject的load和initialize方法

http://www.cocoachina.com/ios/20150104/10826.html

相關文章
相關標籤/搜索