+ (void)load和 + (void)initialize

+ (void)load和 + (void)initialize

+ initialize+ load 是 NSObject 類的兩個(gè)類方法,它們會在運(yùn)行時(shí)自動(dòng)調(diào)用,我們可以利用其特性做一些初始化操作。

initialize和load的區(qū)別在于:load是只要類所在文件被引用就會被調(diào)用,而initialize是在類或者其子類的第一個(gè)方法被調(diào)用前調(diào)用。所以如果類沒有被引用進(jìn)項(xiàng)目,就不會有l(wèi)oad調(diào)用;但即使類文件被引用進(jìn)來,但是沒有使用,那么initialize也不會被調(diào)用。

initialize初探

+ (void)initialize 消息是在該類接收到其第一個(gè)消息之前調(diào)用。

關(guān)于這里的第一個(gè)消息需要特別說明一下,對于 NSObject 的 runtime 機(jī)制而言,其在調(diào)用 NSObject 的 + (void)load 消息不被視為第一個(gè)消息,但是,如果像普通函數(shù)調(diào)用一樣直接調(diào)用 NSObject 的 + (void)load 消息,則會引起 + (void)initialize 的調(diào)用。反之,如果沒有向 NSObject 發(fā)送第一個(gè)消息,+ (void)initialize 則不會被自動(dòng)調(diào)用。

在應(yīng)用程序的生命周期中,runtime 只會向每個(gè)類發(fā)送一次 + (void)initialize 消息.

如果該類是子類,且該子類中沒有實(shí)現(xiàn) + (void)initialize 消息,或者子類顯示調(diào)用父類實(shí)現(xiàn) [super initialize], 那么則會調(diào)用其父類的實(shí)現(xiàn)。也就是說,父類的 + (void)initialize 可能會被調(diào)用多次。

如果類包含分類(擴(kuò)展 catagory),且分類重寫了initialize方法,那么則會調(diào)用分類的 initialize 實(shí)現(xiàn),而原類的該方法實(shí)現(xiàn)不會被調(diào)用。

這個(gè)機(jī)制同 NSObject 的其他方法(除 + (void)load 方法) 一樣,即如果原類同該類的分類包含有相同的方法實(shí)現(xiàn),那么原類的該方法被隱藏而無法被調(diào)用。

父類的 initialize 方法先于子類的 initialize 方法調(diào)用。

實(shí)例:

@interface People : NSObject

@end

@implementation People

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

@end

@interface Student : People

@end

@implementation Student

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

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    Student *student = [[Student alloc] init];
}
@end

輸出:

+[People initialize]
+[Student initialize]

若再次調(diào)用初始化實(shí)例,initialize 不再調(diào)用。

擴(kuò)展情況下:

@interface Student (Score)

@end

@implementation Student (Score)

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

輸出:

+[People initialize]
+[Student(Score) initialize]

load初探

+ (void)load 會在類或者類的分類添加到 Objective-c runtime 時(shí)調(diào)用,該調(diào)用發(fā)生在 application:willFinishLaunchingWithOptions: 調(diào)用之前調(diào)用。

父類的 +load 方法先于子類的 +load 方法調(diào)用,分類的 +load 方法先于類本身的 +load 方法調(diào)用。

Runtime調(diào)用+(void)load時(shí)沒有autorelease pool:

原因是runtime調(diào)用+(void)load的時(shí)候,程序還沒有建立其autorelease pool,所以那些會需要使用到autorelease pool的代碼,都會出現(xiàn)異常。這一點(diǎn)是非常需要注意的,也就是說放在+(void)load中的對象都應(yīng)該是alloc出來并且不能使用autorelease來釋放。

不需要顯示使用super調(diào)用父類中的方法

super的方法會成功調(diào)用,但是這是多余的,因?yàn)閞untime對自動(dòng)對父類的+(void)load方法進(jìn)行調(diào)用,而+(void)initialize則會隨子類自動(dòng)激發(fā)父類的方法(如Apple文檔中所言)不需要顯示調(diào)用。另一方面,如果父類中的

實(shí)例:

//父類
@interface People : NSObject
@end
@implementation People

+ (void)initialize {
    NSLog(@"%@ , %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end
//子類
@interface Student : People
@end
@implementation Student
+ (void)initialize {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end

//子類分類
@interface Student (Score)
@end
@implementation Student (Score)
+ (void)initialize {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end

輸出:

People , +[People initialize]
People, +[People load]
Student, +[Student(Score) initialize]
Student, +[Student load]
Student +[Student(Score) load]

實(shí)例二:

//父類
@interface People : NSObject
@end
@implementation People
+ (void)initialize {
    NSLog(@"%@ , %s", [self class], __FUNCTION__);
}
@end
//子類
@interface Student : People
@end
@implementation Student
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end

輸出:

People , +[People initialize]
Student , +[People initialize]
Student, +[Student load]

當(dāng)子類沒有實(shí)現(xiàn) +initialize 而父類有其實(shí)現(xiàn)時(shí),父類的實(shí)現(xiàn)調(diào)用了兩次,且 +initialize 的調(diào)用在 +load 調(diào)用之前,這是因?yàn)槲覀冊?+load 實(shí)現(xiàn)中包含 [self class] 的調(diào)用。

總結(jié):

+(void)load

執(zhí)行時(shí)機(jī)    在程序運(yùn)行后立即執(zhí)行
若自身未定義,是否沿用父類的方法?   否
類別中的定義  全都執(zhí)行,但后于類中的方法

+(void)initialize

執(zhí)行時(shí)機(jī)    在類的方法第一次被調(diào)時(shí)執(zhí)行
若自身未定義,是否沿用父類的方法?   是
類別中的定義  覆蓋類中的方法,只執(zhí)行一個(gè)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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