單例模式只能修改無法釋放,直到程式結束。
我們下面一步一步來做一個單例模式程式
(1)單例一旦建立,是永遠存在於記憶體中的,所以需要建立一個全域性量
static MySingletonClass *sharedSingleTonObj=nil;
(2)既然是單例,一定有一個構造方法直接忽略跳過例項物件的生成過程。據此看來“類方法”最合適不過了
+(MySingletonClass *)sharedSingleton { //多執行緒安全的關鍵字,相關概念可以參考多執行緒程式設計章節 @synchronized(self) { //建立 if(sharedSingletonObj==nil) { sharedSingletonObj= [[super allocWithZone:NULL] init]; } //發出必要警告 else { NSLog(@"單例物件已經存在!"); } } return sharedSingletonObj; }
(3)如果對sharedSingletonObj執行了copy呢?我們需要重新寫copy方法
-(id)copyWithZone:(NSZone *)zone { return self; }
(4)如果對sharedSingletonObj執行了retain呢?我們同樣需要重寫retain方法。
-(id)retain { return self; }
(5)繼續對release和autorelease的方法重寫
-(void)release { } -(id)autorelease { return self; }
(6)重要的一點!我們需要實現NSObjec裡面,關於引用計數API的重寫以避免因為引用計數為0導致dealloc的觸發
-(NSUInteger)retainCount { //是一個無限大的int數,避免額系統自動觸發單例dealloc方法 //也可以明確告知呼叫者,這是一個單例模式 return NSUIntegerMax; }
(7)最後,你會發現就這樣讓人使用的話,如果不通過類方法建立物件轉而呼叫alloc建立,則每次會分配新記憶體引用計數+1,顯然alloc方法勢必也不要重寫
+(id)allocWithZone:(NSZone *)zone { //直接套用sharedSingleton,retain 符合alloc慣例 //使類方法返回的物件的引用計數+1,此處retain根據上面的重寫內容,不做任何事情 return [[MySingletonClass sharedSingleton] retain]; }
我們需要注意的時:往往只需要一個單例物件而已,但是如果仍相用alloc和init建立這個類的其他物件,那上述寫法中,我們不需要重寫2,3,4,5,6的程式碼
注:如果用gcd的話 ,只要在.m檔案中實現這就可以 .h檔案中宣告一下這個 + (XEMessageData*) sharedInstance;
+ (XEMessageData*) sharedInstance { static XEMessageData* sharedInstance; static dispatch_once_t predicate; dispatch_once(&predicate,^{ sharedInstance = [[self alloc] init]; sharedInstance.tempConversationMessageID2ConversationID = [[NSMutableDictionary alloc] init]; }); return sharedInstance; }