標籤:不清楚 繼承 一段 操作 str 安全執行緒 self oid view
可能有些還不清楚load和initialize的區別,下面簡單說一下:
首先說一下 + initialize 方法:蘋果官方對這個方法有這樣的一段描述:這個方法會在 第一次初始化這個類之前 被調用,我們用它來初始化靜態變數.
initialize方法的調用時機,當向該類發送第一個訊息(一般是類訊息首先調用,常見的是alloc)的時候,先調用類中的,再調用類別中的(類別中如果有重寫);如果該類只是引用,沒有調用,則不會執行initialize方法。
兩者方法的共同點:自動調用父類的,不需要super操作;自動調用僅僅會調用一次(不包括外部顯示調用).
load 方法會在載入類的時候就被調用,也就是 ios 應用啟動的時候,就會載入所有的類,就會調用每個類的 + load 方法.
load方法的調用時機,main函數之前,先調用類中的,再調用類別中的(類別中如果有重寫).
代碼示範:
#pragram ---main函數中的代碼---#import <UIKit/UIKit.h>#import "AppDelegate.h"int main(int argc, char * argv[]) { NSLog(@"%s",__func__); @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); }}#pragram ---基於NSObject的Person類---#import "Person.h"@implementation Person+ (void)load{ NSLog(@"%s",__func__);}+ (void)initialize{ [super initialize]; NSLog(@"%s %@",__func__,[self class]);}- (instancetype)init{ if (self = [super init]) { NSLog(@"%s",__func__); } return self;}@end#pragram ---基於Person的Son類---#import "Girl.h"@implementation Girl+ (void)load{ NSLog(@"%s ",__func__);}+ (void)initialize{ [super initialize]; NSLog(@"%s ",__func__);}- (instancetype)init{ if (self = [super init]) { NSLog(@"%s",__func__); } return self;}@end
輸出日誌:
2017-07-07 09:28:36.535 initialize[1572:27457]] +[Person load]2017-07-07 09:28:36.535 initialize[1572:27457]] +[Girl load] 2017-07-07 09:28:36.535 initialize[1572:27457]] main
這說明在我並沒有對類做任何操作的情況下,+load 方法會被預設執行,並且是在 main 函數之前執行的。
#接下來我們來查看一下 + initialize 方法,先在 ViewController 中建立 Person 和 Girl 對象:
#import "ViewController.h"#import "Person.h"#import "Son.h"#import "Girl.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; Person * p1 = [Person new]; Person * p2 = [Person new]; Girl *c1 = [Girl new]; Girl *c2 = [Girl new];}@end
輸出日誌:
2017-07-07 09:34:57.134 initialize[1840:100060] +[Person load]2017-07-07 09:34:57.135 initialize[1840:100060] +[Girl load] 2017-07-07 09:34:57.136 initialize[1840:100060] main2017-07-07 09:34:57.198 initialize[1840:100060] +[Person initialize] Person2017-07-07 09:34:57.198 initialize[1840:100060] -[Person init]2017-07-07 09:34:57.198 initialize[1840:100060] -[Person init]2017-07-07 09:34:57.198 initialize[1840:100060] +[Girl initialize] 2017-07-07 09:34:57.199 initialize[1840:100060] -[Girl init]2017-07-07 09:34:57.199 initialize[1840:100060] -[Girl init]
+ initialize 方法類似一個懶載入,如果沒有使用這個類,那麼系統預設不會去調用這個方法,且預設只載入一次;
+ initialize 的調用發生在 +init 方法之前.
那麼+ initialize 在父類與子類之間的關係是什麼楊,我們建立一個繼承自 Person 類的 Son類:
#pragram ---ViewController 中的代碼---#import "ViewController.h"#import "Person.h"#import "Son.h"#import "Girl.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; Person * p1 = [Person new]; Person * p2 = [Person new]; Son*s = [Son new];}@end
輸出日誌:
2017-07-07 09:50:14.140 initialize[1893:109979] +[Person load]2017-07-07 09:50:14.142 initialize[1893:109979] +[Son load]2017-07-07 09:50:14.142 initialize[1893:109979] +[Girl load] 2017-07-07 09:50:14.142 initialize[1893:109979] main2017-07-07 09:50:14.203 initialize[1893:109979] +[Person initialize] Person2017-07-07 09:50:14.203 initialize[1893:109979] -[Person init]2017-07-07 09:50:14.203 initialize[1893:109979]] -[Person init]2017-07-07 09:50:14.204 initialize[1893:109979] +[Person initialize] Son2017-07-07 09:50:14.204 initialize[1893:109979] -[Person init]
我們會發現 Person 類的 + initialize 方法又被調用了,但是查看一下是子類 Son 調用的,也就是建立子類的時候,子類會去調用父類的 + initialize 方法。
這是因為在建立子類對象時,首先要建立父類對象,所以會調用一次父類的initialize方法,然後建立子類時,儘管自己沒有實現initialize方法,但還是會調用到父類的方法。
雖然initialize方法對一個類而言只會調用一次,但這裡由於出現了兩個類,所以調用兩次符合規則,但不符合我們的需求。正確使用initialize方法的姿勢如下
// In Person.m+ (void)initialize { if (self == [Person class]) { NSLog(@"Initialize Person, caller Class %@", [self class]); }}
加上判斷後,就不會因為子類而調用到自己的initialize方法了.
總結:
load和initialize方法都會在執行個體化對象之前調用,以main函數為分水嶺,前者在main函數之前調用,後者在之後調用。這兩個方法會被自動調用,不能手動調用它們。
load和initialize方法都不用顯示的調用父類的方法而是自動調用,即使子類沒有initialize方法也會調用父類的方法,而load方法則不會調用父類。
load方法通常用來進行Method Swizzle,initialize方法一般用於初始化全域變數或靜態變數。
load和initialize方法內部使用了鎖,因此它們是安全執行緒的。實現時要儘可能保持簡單,避免阻塞線程,不要再使用鎖。
iOS load和initialize的區別