
對象初始化有兩種方式:[class new] 與 [[class alloc] init]
對于后者,有分配和初始化的過程,alloc 從應(yīng)用程序的虛擬地址空間上為該對象分配足夠的內(nèi)存,并且將新對象的引用計(jì)數(shù)加1、將對象的成員變量初始為零,init 會做真正的初使化工作,為對象的實(shí)例變量賦予合理有用的值。
一般不推薦使用[class new],而推薦使用[[class alloc] init],查看源碼分析一下:
+ new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
//而 alloc/init 像這樣:
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{
return self;
}
發(fā)現(xiàn)[class new]默認(rèn)調(diào)用 alloc與init方法,那么我們無法使用自定義的初始化方法,多了更多的局限性。那么[class alloc] init] 會更方便, 當(dāng)然[class alloc] init] 的設(shè)計(jì)也是由于歷史的原因。
為啥這么寫?
- (instancetype)init
{
if (self = [super init]) {
// Custom initialization
}
return self;
}
我們知道alloc返回一個(gè)有效的未初始化的對象實(shí)例。對于self是alloc 返回的指針,同時(shí)可以在所有的方法作用域內(nèi)訪問。
但是對于 super,它只是一個(gè)"編譯器指示符",告訴編譯器在父類中搜索方法的實(shí)現(xiàn)。
優(yōu)先調(diào)用[super init] 是為了使超類完成它們自己的初始化工作。
那么 if (self = [super init])又是做啥?
這里是擔(dān)心父類初始化失敗,如果初始化一個(gè)對象失敗,就會返回nil,當(dāng)返回nil的時(shí)候self = [super init]測試的主體就不會再繼續(xù)執(zhí)行。如果不這樣做,你可能會操作一個(gè)不可用的對象,它的行為是不可預(yù)測的,最終可能會導(dǎo)致你的程序崩潰。
理解 Self & Super
看到網(wǎng)上一道經(jīng)典的題目:
@implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
self表示當(dāng)前這個(gè)類的對象,而super是一個(gè)編譯器標(biāo)示符,和self指向同一個(gè)消息接受者。在本例中,無論是[self class]還是[super class],接受消息者都是Son對象,但super與self不同的是,self調(diào)用class方法時(shí),是在子類Son中查找方法,而super調(diào)用class方法時(shí),是在父類Father中查找方法。
當(dāng)調(diào)用[self class]方法時(shí),會轉(zhuǎn)化為objc_msgSend函數(shù),這個(gè)函數(shù)定義如下:
id objc_msgSend(id self, SEL op, ...)
這時(shí)候就開始了消息傳遞和轉(zhuǎn)發(fā)的過程,會先從Cache 中查找方法,然后當(dāng)前類,如果還是查找不到會去父類,直至NSObject類
對于NSObject類中,- (Class)class的實(shí)現(xiàn)如下:
- (Class)class {
return object_getClass(self);
}
所以打印結(jié)果為Son
當(dāng)調(diào)用[super class]方法時(shí),會轉(zhuǎn)化為objc_msgSendSuper,這個(gè)函數(shù)定義如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
objc_msgSendSuper函數(shù)第一個(gè)參數(shù)super的數(shù)據(jù)類型是一個(gè)指向objc_super的結(jié)構(gòu)體
struct objc_super {
__unsafe_unretained id receiver;
__unsafe_unretained Class super_class;
};
結(jié)構(gòu)體包含兩個(gè)成員,第一個(gè)是receiver,表示類的實(shí)例。第二個(gè)成員是記錄當(dāng)前類的父類是什么,會優(yōu)先從Father這個(gè)類里去找- (Class)class,然后進(jìn)行消息傳遞的過程。
會發(fā)現(xiàn)不管是self、還是super指向消息接受者是一樣的,并且經(jīng)過消息傳遞,最終處理消息的方法都是NSObject中的- (Class)class方法。