做爲 NSObject 類中的 2 個方法 initialize 和 load 一直被咱們所熟知,可是又沒有具體去深刻的瞭解,今天結合 Apple 官方文檔,咱們來深刻了解一下 initialize 和 load 方法 。objective-c
看文檔能夠得知 initialize 方法的做用是在 class 收到第一個消息以前初始化 class。安全
Initializes the class before it receives its first message.
+ (void)initialize;
複製代碼
接下來咱們用代碼來探究 initialize 這個方法,咱們有 3 個 class ,分別是 Man,Woman,Person。 其中 Man 和 Woman 都繼承自 Person 。app
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
#import "Person.h"
@implementation Person
+(void)initialize{
NSLog(@"call person initialize");
}
@end
複製代碼
#import "Person.h"
@interface Man : Person
@end
#import "Man.h"
@implementation Man
@end
複製代碼
#import "Person.h"
@interface Woman : Person
@end
#import "Woman.h"
@implementation Woman
@end
複製代碼
在 main.m 方法代碼以下:ui
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
}
return 0;
}
複製代碼
咱們運行程序獲得以下輸出this
call person initialize
複製代碼
在 Person 的 initialize 方法設置斷點,查看堆棧調用,Person 調用的第一個方法確實是 initialize ,該方法在 Person 收到第一個消息以前初始化 Person。spa
接下來修改 main.m 的代碼,同時生成 Person ,Man,Woman 的對象實例。線程
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
Man *m = [[Man alloc] init];
Woman *w = [[Woman alloc] init];
}
return 0;
}
複製代碼
運行程序,查看控制檯輸出code
call person initialize
call person initialize
call person initialize
複製代碼
咱們能夠看出若是子類沒有實現 initialize 方法,runtime 會調用父類的 initialize 實現,那麼咱們就不用在子類中調用 [super initialize] ,同時也意味着父類的 initialize 會被屢次調用,那麼咱們能夠採用以下的方式來避免這個問題。orm
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
複製代碼
那若是 Person子類 Man 和 Woman 都實現 initialize 方法呢?cdn
@implementation Man
+(void)initialize{
NSLog(@"call man initialize");
}
+(void)initialize{
NSLog(@"call woman initialize");
}
@end
複製代碼
運行程序,查看控制檯輸出,能夠看到 class 都是調用各自的 initialize 方法實現。
call person initialize
call man initialize
call woman initialize
複製代碼
每一個 class 有且僅有一次 initialize 方法調用,若是想要實現 class 和 category 的分別獨立初始化,咱們應該使用 load 方法。
看文檔能夠得知 class 或者 category 被添加到 runtime 的時候,load 方法就會被調用。
Invoked whenever a class or category is added to the Objective-C runtime;
implement this method to perform class-specific behavior upon loading.
+ (void)load;
複製代碼
接下來咱們用代碼來探究 load 這個方法,仍是用以前的例子,咱們有 3 個 class ,分別是 Man,Woman,Person。 其中 Man 和 Woman 都繼承自 Person 。
Person 類實現了 load 方法
//Person.m
#import "Person.h"
@implementation Person
+(void)initialize{
NSLog(@"call person initialize");
}
+(void)load{
NSLog(@"call person load");
}
// main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
}
return 0;
}
@end
複製代碼
運行程序,查看控制檯輸出,能夠看出 load 方法調用在 initialize 方法以前。
call person load
call person initialize
複製代碼
接下來修改 main.m 實現
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
Man *m = [[Man alloc] init];
Woman *w = [[Woman alloc] init];
}
return 0;
}
複製代碼
運行程序,查看控制檯輸出,能夠看出子類沒有實現 load 方法的時候,runtime 不會自動調用父類的 load 方法實現
call person load
call person initialize
call man initialize
call woman initialize
複製代碼
接下來修改 Man.m 和 Woman.m 實現
// Man.m
#import "Man.h"
@implementation Man
+(void)initialize{
NSLog(@"call man initialize");
}
+(void)load{
NSLog(@"call man load");
}
@end
// Woman.m
#import "Woman.h"
@implementation Woman
+(void)initialize{
NSLog(@"call woman initialize");
}
+(void)load{
NSLog(@"call woman load");
}
@end
複製代碼
運行程序,查看控制檯輸出,能夠看出,咱們沒有在 Woman 和 Man 中顯式調用父類的 load 方法,可是父類的 load 方法調用都在子類以前,這個和 initialize 方法是同樣的,畢竟是要先有父類初始化,纔會有子類初始化。
call person load
call woman load
call man load
call person initialize
call man initialize
call woman initialize
複製代碼
接下來新建一個 Man 的 category 叫作 Man(Work),
// Mam + Work.m
#import "Man+Work.h"
@implementation Man (Work)
+(void)load{
NSLog(@"call Man (Work) load");
}
@end
複製代碼
運行程序,查看控制檯輸出,能夠看出 category 的 load 方法調用老是在 class 的 load 方法調用以後。
call man load
call Man (Work) load
call man initialize
複製代碼
經過一些代碼例子和官方文檔,咱們能夠知道 initialize 方法的做用是在 class 收到第一個消息以前初始化 class。load 方法的調用時機是在 class 或者 category 被添加到 runtime 的時候。load 方法調用在 initialize 方法以前。