IOS 單例模式的學習

haibo wang發表於2014-04-10

單例模式只能修改無法釋放,直到程式結束。

我們下面一步一步來做一個單例模式程式

(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;
}

 

相關文章