標籤:控制 ios開發 單例 檔案 建立 加鎖 instance font struct
- 什麼是單例模式?
>是開發設計模式(共23種)中的1種
>它可以保證在程式運行過程,一個類只有一個執行個體(一個對象),而且該執行個體易於供外界訪問,從而方便地控制了執行個體個數,並節約系統資源
>使用場合:在整個應用程式中,共用一份資源(這份資源只需要建立初始化1次)
- 單例模式的基本實現
1.懶漢模式
// 1.在該類中定義一個靜態全域變數,防止被外部用extren訪問
static id _instance;
/**
static : 修飾變數
1> 修飾全域變數
* 全域變數的範圍僅限於當前檔案內部,其他檔案不能用extren關鍵字訪問
2> 修飾局部變數 :
* 局部變數的生命週期 跟 全域變數 類似
* 但是不能改變範圍
* 能保證局部變數永遠只初始化1次,在程式運行過程中,永遠只有1分記憶體
*/
/** * 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]; }
- 用GCD實現單例模式
// 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;}
- 非ARC下的單例模式
// 前面與ACR一樣,接著重寫以下方法
// 不做release
- (oneway void)release {}// retain之後還是自己一份- (id)retain { return self;}// 計數器永遠為1- (NSUInteger)retainCount { return 1;}// 防止被放進自動計數池釋放- (id)autorelease { return self;}
- 用宏定義實現單例(適配ARC和MRC)
// 建立一個.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
iOS開發-單例模式