iOS initialize 和load

記錄一下initializeload方法的調(diào)用時機

問題一 loadinitialize哪個更早執(zhí)行?

1. main函數(shù)

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        NSLog(@"%s",__FUNCTION__);
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

2. 繼承自NSObject的Person類

#import "Person.h"

@implementation Person

+ (void)load {
    NSLog(@"%s",__FUNCTION__);
}

+ (void)initialize {
    [super initialize];
    NSLog(@"%s %@",__FUNCTION__, [self class]);
}

- (instancetype)init {
    self = [super init];
    if (self) {
        NSLog(@"%s",__FUNCTION__);
    }
    return self;
}

@end

運行--結(jié)果


結(jié)果1

只執(zhí)行了load, 未調(diào)用initialize, 猜測是因為未實例化Person對象

3. 實例化Person對象

在ViewController中為Person創(chuàng)建一個實例對象

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Person *p1 = [Person new];
}

運行--結(jié)果


結(jié)果2

可以看到, 先調(diào)用load, 然后調(diào)用main, 由于實例化了一個Person對象, 所以調(diào)用了initialize方法, 最后是init方法

結(jié)論2: load早于main早于initialize早于init

還有一些大神總結(jié)的區(qū)別

load

  1. 對于加入運行期系統(tǒng)的類及分類,必定會調(diào)用此方法,且僅調(diào)用一次。

  2. iOS會在應(yīng)用程序啟動的時候調(diào)用load方法,在main函數(shù)之前調(diào)用

  3. 執(zhí)行子類的load方法前,會先執(zhí)行所有超類的load方法,順序為父類->子類->分類

  4. 在load方法中使用其他類是不安全的,因為會調(diào)用其他類的load方法,而如果關(guān)系復(fù)雜的話,就無法判斷出各個類的載入順序,類只有初始化完成后,類實例才能進行正常使用

  5. load 方法不遵從繼承規(guī)則,如果類本身沒有實現(xiàn)load方法,那么系統(tǒng)就不會調(diào)用,不管父類有沒有實現(xiàn)(跟下文的initialize有明顯區(qū)別)

  6. 盡可能的精簡load方法,因為整個應(yīng)用程序在執(zhí)行l(wèi)oad方法時會阻塞,即,程序會阻塞直到所有類的load方法執(zhí)行完畢,才會繼續(xù)

  7. load 方法中最常用的就是方法交換method swizzling

initialize

  1. 在首次使用該類之前由運行期系統(tǒng)(非人為)調(diào)用,且僅調(diào)用一次

  2. 惰性調(diào)用,只有當(dāng)程序使用相關(guān)類時,才會調(diào)用

  3. 運行期系統(tǒng)會確保initialize方法是在線程安全的環(huán)境中執(zhí)行,即,只有執(zhí)行initialize的那個線程可以操作類或類實例。其他線程都要先阻塞,等待initialize執(zhí)行完

  4. 如果類未實現(xiàn)initialize方法,而其超類實現(xiàn)了,那么會運行超類的實現(xiàn)代碼,而且會運行兩次(load 第5點)

    (1) initialize 遵循繼承規(guī)則
    (2) 初始化子類的的時候會先初始化父類,然后會調(diào)用父類的initialize方法,而子類沒有覆寫initialize方法,因此會再次調(diào)用父類的實現(xiàn)方法
    (3) 鑒于此,initialize方法實現(xiàn)如下:

   + (void)initialize {
      if (self == [People class]) {
          NSLog(@"%@ initialize", self);
      }
  }
  1. initialize方法也需要盡量精簡,一般只應(yīng)該用來設(shè)置內(nèi)部數(shù)據(jù),比如,某個全局狀態(tài)無法在編譯期初始化,可以放在initialize里面。
static NSMutableArray *kSomeObjects;
 @implementation People
 + (void)initialize {
     if (self == [People class]) {
         kSomeObjects = [NSMutableArray new]; 
     }
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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