2014-10-31 83 views
1

這與標準singleton pattern稍有不同,因爲如果所有對象的外部引用都已釋放,那麼單例也將被釋放。然後,稍後,當請求一個新的對象時,將創建一個新的單例。所以,這樣的事情:如何確保Objective-C中任何時候只有一個類的實例?

MyThing *thing1 = [MyThing new]; 
MyThing *thing2 = [MyThing new]; 
// thing1 & thing2 are the same object. 

thing1 = nil; 
thing2 = nil; 

thing1 = [MyThing new]; 
thing2 = [MyThing new]; 
// thing1 and thing2 are a the same objet, but it's a different object than above. 

我試圖用微弱的靜態變量來掛在我的範圍的單,但沒有工作,因爲我沒有辦法來增加ARC下的保留計數。這讓我想知道:這甚至有可能嗎?

+0

爲什麼你需要這個? – Abizern 2014-10-31 21:18:05

+1

看起來像通過工廠訪問的弱引用會做到這一點。工廠必須像單身工廠一樣工作。 – 2014-10-31 21:21:38

+0

因爲我不會經常需要這個對象,但是當我這樣做時,我會想要一次訪問一堆分離的地方中的同一個對象。 – theory 2014-10-31 21:21:52

回答

1

重寫allocWithZone:管理單個靜態實例。如果無,則創建一個新的,如果不是零,則返回它的保留版本。

實現dealloc和當調用nil時的單個靜態實例。

我不確定這是否適用於ARC,您可能需要爲該文件禁用弧。

保持物體周圍的代價有多昂貴?遵循標準的單例模式並忘記它,肯定沒那麼麻煩。

+0

您還需要修改'init',以便在您獲得已存在的對象時不會重新初始化。 – 2014-10-31 21:36:15

+0

是的,這似乎是正確的答案。我在'-init'中執行了它,但移動了它'+ allocWithZone:',現在它按預期工作。現在只需要弄清楚如何讓'-init'對現有對象不做任何事情...... – theory 2014-10-31 21:52:39

+0

我想我已經明白了,雖然它不是通用化的(檢查是否在'-init'中設置了ivar)。測試通過,但是在釋放對象之後,在創建新對象之前,我必須調用'NSLog()'或者取回具有相同地址的對象。即使使用NSLog(),我仍然有時會在同一個地址獲得一個對象。 – theory 2014-10-31 22:04:25

0

基於@ KirkSpaziani的答案,這是我想出來的:

static __weak MyTHing *currentThing = nil; 

+ (instancetype)allocWithZone:(struct _NSZone *)zone { 
    __block id thing = nil; 
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     if (currentThing == nil) { 
      currentThing = thing = [super allocWithZone:zone]; 
     } else { 
      thing = currentThing; 
     } 
    }); 
    return thing; 
} 

- (void)dealloc { 
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     currentThing = nil; 
    }); 
} 

這假設初始值設定處理「髒數據」,作爲described by Mike Ash

+0

現在,如果只有我可以阻止Objective-C在objet發佈後使用相同的內存地址,我可以進行一個很好的測試以確保它能正常工作。實際上,我可以通過添加一個'NSLog()'調用的日誌來看到它的工作原理,但我會更加樂於進行可靠的單元測試。 – theory 2014-10-31 22:51:42

+0

你應該看看http://stackoverflow.com/questions/7274360/how-objective-c-singleton-should-implement-init-method – rmaddy 2014-10-31 23:47:30

+0

登錄dealloc?這應該是最可靠的方法。此外,如果多個線程可以創建這些對象,請考慮使用GCD的dispatch_sync而不是@synchronized(self) - 它應該更具性能。 – KirkSpaziani 2014-11-01 22:23:02

相關問題