// 1.在該類中定義一個靜態的全局變量,防止被外部用extren訪問
static id _instance;
/**設計模式
static : 修飾變量緩存
1> 修飾全局變量安全
* 全局變量的做用域僅限於當前文件內部,其餘文件不能用extren關鍵字訪問cookie
2> 修飾局部變量 : 多線程
* 局部變量的生命週期 跟 全局變量 相似spa
* 可是不能改變做用域線程
* 能保證局部變量永遠只初始化1次,在程序運行過程當中,永遠只有1份內存設計
*/code
/** * 2.重寫它這個類的llocWithZone:方法,確保只爲你這個類分配一次內存地址 * alloc方法內部會調用這個方法 */ + (id)allocWithZone:(struct _NSZone *)zone { if (_instance == nil) { // 防止頻繁加鎖 @synchronized(self) { // 加鎖,避免在多線程中出錯而建立多個對象 if (_instance == nil) { // 防止建立屢次 _instance = [super allocWithZone:zone]; } } } return _instance; } // 3.提供一個shared方法讓外界調用這個單例(通常單例都會提供這個方法),確保只init一次 + (instancetype)sharedMusicTool { if (_instance == nil) { // 防止頻繁加鎖 @synchronized(self) { if (_instance == nil) { // 防止建立屢次 _instance = [[self alloc] init]; } } } return _instance; } // 4.重寫copyWithZone:方法,避免使用copy時建立多個對象 - (id)copyWithZone:(NSZone *)zone { return _instance; }
2.餓漢模式(當類加載到OC運行環境中(內存)時,就會調用一次生成這個單例(一個類只會加載一次))對象
// 1.在該類中定義一個靜態的全局變量,防止被外部用extren訪問 static id _instance; /** * 2.重寫它這個類的llocWithZone:方法,這裏不用加鎖,由於程序剛啓動,線程還沒加載,不會出現線程不安全的問題 */ + (id)allocWithZone:(struct _NSZone *)zone { if (_instance == nil) { // 防止建立屢次 _instance = [super allocWithZone:zone]; } return _instance; } // 3.提供一個shared方法讓外界調用這個單例(通常單例都會提供這個方法) + (instancetype)sharedMusicTool { return _instance; } // 4.重寫copyWithZone:方法,避免使用copy時建立多個對象 - (id)copyWithZone:(NSZone *)zone { return _instance; } // 5.重寫load這個類方法,在裏面alloc它 // 這個方法在程序啓動,加載類的時候會調用一次 + (void)load { _instance = [[self alloc] init]; }
// 1. static id _instance; /** * 2.用GCD的dispatch_once方法重寫 */ + (id)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } // 3. + (instancetype)sharedMusicTool { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } // 4. - (id)copyWithZone:(NSZone *)zone { return _instance; }
// 前面與ACR同樣,接着重寫如下方法
// 不作release
- (oneway void)release { } // retain以後仍是本身一份 - (id)retain { return self; } // 計數器永遠爲1 - (NSUInteger)retainCount { return 1; } // 防止被放進自動計數池釋放 - (id)autorelease { return self; }
// 新建一個.h文件或pch文件,把一下代碼copy進去。在須要實現單例的類中import進去並使用宏(括號裏面傳相應的類名)便可
// 在.h文件使用的宏定義 #define HJSingletonH(name) + (instancetype)shared##name; #if __has_feature(objc_arc) // 當前的編譯器環境是ARC // 在.m文件使用的宏定義 #define HJSingletonM(name) \ static id _instace; \ \ + (id)allocWithZone:(struct _NSZone *)zone \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instace = [super allocWithZone:zone]; \ }); \ return _instace; \ } \ \ + (instancetype)shared##name \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instace = [[self alloc] init]; \ }); \ return _instace; \ } \ \ - (id)copyWithZone:(NSZone *)zone \ { \ return _instace; \ } #else // 當前的編譯器環境是MRC // 在.m文件使用的宏定義 #define HJSingletonM(name) \ static id _instace; \ \ + (id)allocWithZone:(struct _NSZone *)zone \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instace = [super allocWithZone:zone]; \ }); \ return _instace; \ } \ \ + (instancetype)shared##name \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instace = [[self alloc] init]; \ }); \ return _instace; \ } \ \ - (id)copyWithZone:(NSZone *)zone \ { \ return _instace; \ } \ - (oneway void)release {} \ - (id)retain {return self;} \ - (NSUInteger)retainCount {return 1;} \ - (id)autorelease {return self;} #endif