在iOS中,單例模式是比較常用的一種模式燥狰,保證相關(guān)代碼只會執(zhí)行一次揣云,但有時候會有一種場景捕儒,需要銷毀單例進行重建。
如果不采用GCD提供的dispatch_once方法邓夕,需要加鎖操作刘莹,是比較耗性能的。
那么這個時候如何繼續(xù)采用dispatch_once方法焚刚?
dispatch_once_t的描述是:
typedef long dispatch_once_t;
GCD創(chuàng)建:dispatch_once中dispatch_once_t類型為typedef long
? onceToken= 0点弯,線程執(zhí)行dispatch_once的block中代碼
? onceToken= -1,線程跳過dispatch_once的block中代碼不執(zhí)行
? onceToken= 其他值矿咕,線程被線程被阻塞抢肛,等待onceToken值改變
用途:限制創(chuàng)建狼钮,提供全局調(diào)用,節(jié)約資源和提高性能捡絮。參考
常見的應(yīng)用場景:
? UIApplication
? NSNotificationCenter
? NSFileManager
? NSUserDefaults
? NSURLCache
? NSHTTPCookieStorage
dispatch_once在判斷是否需要執(zhí)行的關(guān)鍵語句:
if(DISPATCH_EXPECT(*predicate, ~0l) != ~0l) {
dispatch_once_f(predicate, context, function);
}
可以了解到 dispatch_once_t參數(shù)的初始值就是0l熬芜,只需要重置dispatch_once_t參數(shù)及實例參數(shù),具體代碼如下:
static SpTest *sInstance = nil;
static dispatch_once_t onceToken;
+ (instancetype)sharedManager {
dispatch_once(&onceToken, ^{
sInstance = [[self alloc] init];;
NSLog(@"dispatch once");
});
return sInstance;
}
+ (void)tearDown {
sInstance=nil;
onceToken=0l;
}
回過頭來想想福稳,其實這樣實現(xiàn)是一種比較粗陋的方式涎拉,需要考慮在銷毀的同時實例的使用狀況等,其實是違背dispatch_once使用的初衷的的圆。
不排除真的有這種單例需要銷毀的場景曼库,但多數(shù)需要銷毀的單例實際上可能不適用于單例這種模式,可能需要重新考慮架構(gòu)設(shè)計問題略板。