不管是愛仍是恨,你都須要單例。實際上每一個iOS或Mac OS應用都至少會有
UIApplication或
NSApplication.
什麼是單例呢?Wikipedia是如此定義的:
在軟件工程中,單例是一種用於實現單例的數學概念,即將類的實例化限制成僅一個對象的設計模式。
或者個人理解是:
單例是一種類,該類只能實例化一個對象。
儘管這是單例的實際定義,但在Foundation框架中不必定是這樣。好比
NSFileManger和
NSNotificationCenter,分別經過它們的類方法
defaultManager和
defaultCenter獲取。儘管不是嚴格意義的單例,這些類方法返回一個能夠在應用的全部代碼中訪問到的類的共享實例。在本文中咱們也會採用該方法。
使用Objective-C實現單例模式的最佳方式向來有不少爭論,開發者(包括Apple在內)彷佛每幾年就會改變他們的想法。當Apple引入了
Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0),他們也引入了一個很適合用於實現單例模式的函數。
該函數就是
dispatch_once:
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
該函數接收一個
dispatch_once用於檢查該代碼塊是否已經被調度的謂詞(是一個長整型,實際上做爲
BOOL使用)。它還接收一個但願在應用的生命週期內僅被調度一次的代碼塊,對於本例就用於shared實例的實例化。
dispatch_once不只意味着代碼僅會被運行一次,並且仍是線程安全的,這就意味着你不須要使用諸如
@synchronized 之類的來防止使用多個線程或者隊列時不一樣步的問題。
若是被多個線程調用,該函數會同步等等直至代碼塊完成。
實際要如何使用這些呢?
好吧,假設有一個
AccountManager類,你想在整個應用中訪問該類的共享實例。你能夠按以下代碼簡單實現一個類方法:
+ (AccountManager *)sharedManager {
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate; dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}
這就意味着你任什麼時候候訪問共享實例,須要作的僅是:
AccountManager *accountManager = [AccountManager sharedManager];
就這些,你如今在應用中就有一個共享的實例,該實例只會被建立一次。
該方法有不少優點:
1 線程安全
2 很好知足靜態分析器要求
3 和自動引用計數(ARC)兼容
4 僅須要少許代碼
該方法的劣勢就是它仍然運行建立一個非共享的實例:
AccountManager *accountManager = [[AccountManager alloc] init];
有些時候你但願有這種行爲,但若是正在想要的是僅一個實例被實例化就須要注意這點。