在iOS開發中,單例是最有用的設計模式之一。它是在代碼間共享數據而不需要手動傳遞參數的一種最有用的方法。關於單例和其他設計模式,請參考這本書:
《Cocoa design pattern》 背景 單例是一種重要的概念,它是一種極其便利的設計模式。在iPhone SDK中大量使用了單例的概念,例如,UIApplication的sharedApplication方法,任何時候都會返回一個當前應用程序的UIApplication實例。 將如何實現 使用下列代碼實現一個單例類:MyManager.h #import<foundation/Foundation.h> @interfaceMyManager : NSObject { NSString *someProperty; } @property(nonatomic, retain) NSString *someProperty; +(id)sharedManager; @end MyManager.m #import"MyManager.h" @implementationMyManager @synthesizesomeProperty; #pragmamark Singleton Methods +(id)sharedManager { static MyManager*sharedMyManager = nil; static dispatch_once_tonceToken; dispatch_once(&onceToken, ^{ sharedMyManager = [[self alloc] init]; }); return sharedMyManager; } -(id)init { if (self = [super init]) { someProperty =[[NSString alloc] initWithString:@"Default Property Value"]; } return self; } -(void)dealloc { // Should never be called, but justhere for clarity really. } @end我們定義了一個靜態變量叫做sharedMyManager,它在sharedManager方法中只會被實例化一次。通過GCD的dispath_once方法,我們確保sharedMyManager方法只會被創建一次。這是線程安全的,你無需擔心什麼。 但是,如果你不想用GCG,也可以這樣實現sharedManager方法:
非-GCD 代碼 + (id)sharedManager { @synchronized(self) { if (sharedMyManager == nil) sharedMyManager = [[self alloc] init]; } returnsharedMyManager; } 這樣調用單例對象: MyManager *sharedManager = [MyManager sharedManager]; 在我的代碼中,很多地方都使用了這樣的代碼。我用這些單例對象處理CoreLocation或CoreData。 非ARC代碼 如果你不使用ARC(不建議),則應該使用下列代碼: MyManager.h (非ARC) #import "MyManager.h" static MyManager *sharedMyManager = nil; @implementation MyManager @synthesize someProperty; #pragma mark Singleton Methods + (id)sharedManager { @synchronized(self) { if(sharedMyManager == nil) sharedMyManager = [[super allocWithZone:NULL] init]; } return sharedMyManager; } + (id)allocWithZone:(NSZone *)zone { return [[self sharedManager]retain]; } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (unsigned)retainCount { return UINT_MAX; //denotes anobject that cannot be released } - (oneway void)release { // never release } - (id)autorelease { return self; } - (id)init { if (self = [super init]) { someProperty = [[NSString alloc] initWithString:@"Default PropertyValue"]; } return self; } - (void)dealloc { // Should never be called,but just here for clarity really. [someProperty release]; [super dealloc]; } @end