1. 程式人生 > >+load 與 +initialize的區別

+load 與 +initialize的區別

先附上程式碼,load 方法的程式碼 我就不附上,大家可以自己動手測試一下。

@interface XZPerson : NSObject

@end
#import "XZPerson.h"

@implementation XZPerson

+ (void)initialize{
     NSLog(@"XZPerson-initialize");  
}

@end
//////////////////////////////////////////////////////////////////////////////
#import "XZPerson.h"

@interface XZPerson (Eat)

@end
#import "XZPerson+Eat.h"

@implementation XZPerson (Eat)

+ (void)initialize{
    NSLog(@"XZPerson(Eat)-initialize");
}
@end
//////////////////////////////////////////////////////////////////////////////
#import "XZPerson.h"

@interface XZPerson (Drink)
@end
@implementation XZPerson (Drink)

+ (void)initialize{
    NSLog(@"XZPerson(Eat)-initialize");
}
@end
//////////////////////////////////////////////////////////////////////////////

#import "XZPerson.h"

@interface XZStudent : XZPerson

@end
#import "XZStudent.h"

@implementation XZStudent

+ (void)initialize{
    NSLog(@"XZStudent-initialize");
}

@end
//////////////////////////////////////////////////////////////////////////////
#import "XZStudent.h"

@interface XZStudent (Test1)

@end
#import "XZStudent+Test1.h"

@implementation XZStudent (Test1)
+ (void)initialize{
    NSLog(@"XZStudent(Test1)-initialize");
}
@end
//////////////////////////////////////////////////////////////////////////////
#import "XZStudent.h"

@interface XZStudent (Test2)

@end
#import "XZStudent+Test2.h"

@implementation XZStudent (Test1)
+ (void)initialize{
    NSLog(@"XZStudent(Test2)-initialize");
}
@end

結論如下:

一,+load 方法 會在runtime 載入類/分類時呼叫 在程式執行過程中只會呼叫一次。

  1. 先呼叫類的+ load ,按照編譯順序來,先編譯先呼叫
  2. 在呼叫子類的+load 方法之前,會先呼叫父類的。
  3. 假如類有分類,會優先呼叫分類的+load
  4. + load的方法是根據方法地址直接呼叫,並不是經過objc_msgSend 函式呼叫的。
  5. 可以參考runtime的原始碼,objc-os.mm 中的_objc_init 方法中檢視load_images等等

二,+initialize方法會在類第一次接收訊息食呼叫

  1. 先呼叫父類的+initialize方法,在呼叫子類的,只會初始化一次
  2. 如果子類沒有實現+initialize方法會優先呼叫父類的initialize方法,所以父類的initialize方法會被呼叫多次
  3. 如果分類呼叫了+initialize方法,那麼它會覆蓋本身的initialize方法
  4. 按照編譯順序,後編譯的分類有先呼叫。
  5. +initialize是通過objc_msgSend呼叫的。