單例實現(單例宏),實現(宏)
一、什麼是單例
單例就是,一個類,每次建立都是同一個對象。也就是說只能執行個體化一次。
二、如何保證每次建立都是同一個對象
建立一個對象歸根揭底都會經過一個途徑,alloc方法(alloc方法會調用allocWithZone:)。因此只要保證alloc方法只會調用一次,且保證安全執行緒,然後把此對象放在靜態區。以後不管是建立對象還是copy對象都直接返回靜態區的對象。
三、注意點
靜態全域變數不需要考慮釋放的問題(適用於MRC),解決安全執行緒問題可以用互斥鎖或者GCD,後者更好。
也可設定不讓對象重複初始化,即讓初始化方法只能執行一次。
四、具體實現代碼如下
@implementation myManagerstatic id instance;+ (instancetype)allocWithZone:(struct _NSZone *)zone{ // 1、互斥鎖// @synchronized (self) {// if (instance == nil)// {// instance = [super allocWithZone:zone];// }// } // 2、GCD,只執行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (instance == nil) { instance = [super allocWithZone:zone]; } }); return instance;}+ (instancetype)sharedSoundTools{ instance = [[self alloc] init]; return instance;}- (id)copyWithZone:(NSZone *)zone{ return instance;}#pragma mark - MRC 部分代碼- (oneway void)release{ // 什麼都不做}- (instancetype)retain{ // 本想什麼都不做,但它要傳回值 return instance;}- (instancetype)autorelease{ return instance;}- (NSUInteger)retainCount{ // 此處防治有人不明就裡的粗暴釋放對象,比如while迴圈 return ULONG_MAX;}- (instancetype)init{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ self = [super init]; if (self) { self.age = 10; // 只是舉個例子,只初始化一次,可以不設定 } }); return self;}@end
五、單例宏
以下代碼寫在單獨singleton.h檔案裡,使用時直接包含.h標頭檔。
使用方法,.h檔案:singletonInterface(myManager);
.m檔案:singletonImplementation(myManager);
抽取代碼如下:
#define singletonInterface(className) + (instancetype)shared##className;#if __has_feature(objc_arc)// 以下是ARC版本#define singletonImplementation(className) \+ (instancetype)allocWithZone:(struct _NSZone *)zone { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ if (instance == nil) { \ instance = [super allocWithZone:zone]; \ } \ }); \ return instance; \} \+ (instancetype)shared##className { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ instance = [[self alloc] init]; \ }); \ return instance; \} \- (id)copyWithZone:(NSZone *)zone { \ return instance; \}#else// 以下是MRC版本#define singletonImplementation(className) \+ (instancetype)allocWithZone:(struct _NSZone *)zone { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ if (instance == nil) { \ instance = [super allocWithZone:zone]; \ } \ }); \ return instance; \} \+ (instancetype)shared##className { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ instance = [[self alloc] init]; \ }); \ return instance; \} \- (id)copyWithZone:(NSZone *)zone { \ return instance; \} \- (oneway void)release {} \- (instancetype)retain {return instance;} \- (instancetype)autorelease {return instance;} \- (NSUInteger)retainCount {return ULONG_MAX;}#endif// 提示末尾一行不要有 \