初始化方法的標準結構是這樣子的:
- (instancetype)init
{
self = [super init]; // call the designated initializer
if (self) {
// Custom initialization
}
return self;
}
我們主要來看看,這一句:
self = [super init]; // call the designated initializer
問題1:[super init] 到底做了什么?
問題2:為什么把[super init]的值賦值給self?
問題3:我們用過了 alloc init的兩部創建,為什么不是[[super alloc] init]
先來回答問題3,因為這個問題是來搞笑的:
我們看下alloc方法是怎么定義的
+ (instancetype)alloc;
可以看到alloc是一個類方法,而super不是一個類.
然后我們在來看看問題1:
[super init] 的結果可能有三種:
第一種: [super init] 初始化成功,這個是最最正常的情況。
第二種: [super init] 初始化失敗,我們都知道oc的兩步創建,alloc開辟內存空間,init初始化對象,但是init還有另外一個作用,在初始化失敗的時候,init方法會返回一個nil。回頭行文的最上面,如果self為nil,那么if(self)語句的內容,將不被執行,已確保程序健壯安全。
- (instancetype)init
{
self = [super init]; // call the designated initializer
if (self) {
// Custom initialization
}
return self;
}
第三種:self = [super init]執行之后,內存指向了不相關的地址。這種情況的出現,一般是一下幾種情況:單例、類簇、對象為NSNumber類型、父類在初始化的時候釋放了當前對象,然后重新開辟了新的內存地址。
最后,我們來使用《禪與 Objective-C 編程藝術》的原話來回答問題2:
如果你的超類沒有成功初始化它自己,你必須假設你在一個矛盾的狀態,并且在你的實現中不要處理你自己的初始化邏輯,同時返回 nil。如果你不是這樣做,你看你會得到一個不能用的對象,并且它的行為是不可預測的,最終可能會導致你的 app 發生 crash。
一句話概括:
if( self = [super init] )這是一種通常的建議寫法,賦值并測試nil只是為了防止超類在初始化過程中發生改變,返回了不同的對象。
參考:
《禪與 Objective-C 編程藝術》中文版
中文版地址:https://github.com/oa414/objc-zen-book-cn#class-cluster