1、先看看單例的實(shí)現(xiàn)代碼
#import "Singleton.h"
@implementation Singleton
static Singleton* _instance = nil;
+(instancetype) shareInstance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init] ;
//為什么不用下面這句呢?
//為什么要覆蓋allocWithZone方法,到底alloc 和 allocWithZone有什么區(qū)別呢?
//_instance = [[super alloc] init] ;
}) ;
return _instance ;
}
+(id) allocWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
}
-(id) copyWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
}
@end
2、alloc 和 allocWithZone有什么區(qū)別
初始化一個(gè)對(duì)象的時(shí)候,[[Class alloc] init],其實(shí)是做了兩件事。
alloc 給對(duì)象分配內(nèi)存空間,init是對(duì)對(duì)象的初始化,包括設(shè)置成員變量初值這些工作。
而給對(duì)象分配空間,除了alloc方法之外,還有另一個(gè)方法: allocWithZone.
使用alloc方法初始化一個(gè)類的實(shí)例的時(shí)候,默認(rèn)是調(diào)用了allocWithZone的方法。為了保持單例類實(shí)例的唯一性,需要覆蓋所有會(huì)生成新的實(shí)例的方法,如果初始化這個(gè)單例類的時(shí)候不走[[Class alloc] init] ,而是直接 allocWithZone, 那么這個(gè)單例就不再是單例了,所以必須把這個(gè)方法也堵上。
3、什么是NSZone?
NSZone不是一個(gè)對(duì)象,而是使用C結(jié)構(gòu)存儲(chǔ)了關(guān)于對(duì)象的內(nèi)存管理的信息。cocoa Application使用一個(gè)系統(tǒng)默認(rèn)的NSZone來對(duì)應(yīng)用的對(duì)象進(jìn)行管理。
那么在什么時(shí)候你會(huì)想要有一個(gè)自己控制的NSZone呢?當(dāng)默認(rèn)的NSZone里面管理了大量的對(duì)象的時(shí)候。這種時(shí)候,大量對(duì)象的釋放可能會(huì)導(dǎo)致內(nèi)存嚴(yán)重碎片化,cocoa本身有做過優(yōu)化,每次alloc的時(shí)候會(huì)試圖去填滿內(nèi)存的空隙,但是這樣做的話時(shí)間的開銷很大。于是乎,你可以自己創(chuàng)建一個(gè)NSZone,這樣當(dāng)你有大量的alloc請(qǐng)求的時(shí)候就全部轉(zhuǎn)移到指定的NSZone里面去,減少了大量的時(shí)間開銷。而且,使用NSZone還可以一口氣把你創(chuàng)建的zone里面的東西都清除掉,省掉了大量的時(shí)間去一個(gè)個(gè)dealloc對(duì)象。
總的來說,當(dāng)你需要?jiǎng)?chuàng)建大量的對(duì)象的時(shí)候,使用NSZone還是能節(jié)省一些時(shí)間的。多個(gè)對(duì)象在同一時(shí)間alloc可以減少分頁使用,而且在同一個(gè)時(shí)間dealloc可以減少內(nèi)存碎片。
allocWithZone不被Apple鼓勵(lì)使用,基本上多數(shù)時(shí)候程序員也不需要自己去管理自己的zone。