1.ios的單例模式有兩種官方寫(xiě)法:
1)不使用GCD的方式
#import ?"Manager.h"
static ? Manager ? *manager;
@implementation ?Manager
+(Manager *))shareManager {
? ? ? ? ?if (!manager) {
? ? ? ? ? ? ? ? ? ?manager = [super ?allocWithZone:NULL] ?init];
? ? ? ? ? }
? ? ? ? ?return manager;
}
@end;
2)使用GCD的方式
#import ?"Manager.h"?
@implementataion ?Manager?
+(Manager *)shareManager {
? ? ? ? ? ? ?static ?Manager *shareManager;
? ? ? ? ? ? ? static dispatch_once_t? predicate;
? ? ? ? ? ? ?dispatch_once(&predicate, ^{
? ? ? ? ? ? ? ? ? ? ? ? shareManager =[super? allocWithZone:NULL]? init];
? ? ? ? ? ?});
? ? ? ? ? return ? shareManager;
}
//注明:dispatch_once這個(gè)函數(shù)两曼,他可以一次保證整個(gè)應(yīng)用程序生命周期中某段代碼只被執(zhí)行
//不是使用alloc 方法修然,而是調(diào)用[super? allocWithZone:NULL]? init]; 已經(jīng)重載allocWithZone基本的對(duì)象分配方法链烈,所以要借用父類(NSObject)的功能來(lái)幫助處理底層內(nèi)存分配的雜物
當(dāng)我們調(diào)用shareManager方法時(shí)獲取到的對(duì)象是相同的,但是但當(dāng)我們通過(guò)alloc和init以及copy來(lái)構(gòu)造對(duì)象依然會(huì)創(chuàng)建新的實(shí)例。確保對(duì)象的唯一,需要封鎖用戶通過(guò)alloc和init以及copy來(lái)構(gòu)造這條道路。創(chuàng)建對(duì)象的步驟分為申請(qǐng)內(nèi)存(alloc)突雪、初始化(init),要確保對(duì)象的唯一性檩禾,在第一步這個(gè)階段我們就要攔截它挂签,當(dāng)我們調(diào)用alloc方法時(shí),oc內(nèi)部會(huì)調(diào)用allocWithZone這個(gè)方法來(lái)申請(qǐng)內(nèi)存盼产,我們覆寫(xiě)這個(gè)方法饵婆,然后在這個(gè)方法調(diào)用shareManager返回單例對(duì)象。
+(id)allocWithZone:(struct _NSZone *)zone {
? ? ? ? ? ? ? ? ?return ? ? [Manager ? ?shareManager];
}
-(id)copyWithZone:(NSZone *)zone {
? ? ? ? ? ?return? ? [Manager? ? shareManager];
}
-(id)mutablecopyWithZone:(NSZone *)zone {
? ? ? ? ? ?return? ? [Manager? ? shareManager];
}
@end
2.alloc和allocWithZone
在初始化一個(gè)對(duì)象時(shí)([Class alloc] ?init];)其實(shí)做了兩件事,alloc給對(duì)象分配內(nèi)存空間侨核,init是對(duì)對(duì)象的初始化草穆,包括設(shè)置成員變量初始值這些工作。
而給對(duì)象分配內(nèi)存空間搓译,除了alloc方法之外還有另一個(gè)方法:allocWithZone.在NSObject類的官方文檔里面悲柱,allocWithZone方法介紹說(shuō),該方法的參數(shù)是被忽略的些己,正確的做法是傳nil或者NULL參數(shù)給他豌鸡。(這個(gè)方法存在是歷史遺留原因,文檔里memory zone已經(jīng)被棄用了段标,只是歷史原因才保留這個(gè)接口)
實(shí)踐證明涯冠,alloc方法初始化一個(gè)類的實(shí)例時(shí),默認(rèn)調(diào)用allocWithZone的方法逼庞,為了保持單例實(shí)例的唯一性需要覆蓋所有會(huì)生成新的實(shí)例方法蛇更,如果有人初始化這個(gè)單例的時(shí)候不走allocWithZone,而是直接[Class ?alloc] ?init]; ,那么這個(gè)單例就不再是單例了,所以把這個(gè)方法堵上
3.NSZone?