原文: http://www.galloway.me.uk/tutorials/singleton-classes/設計模式
在iOS開發中,單例是最有用的設計模式之一。它是在代碼間共享數據而不須要手動傳遞參數的一種最有用的方法。關於單例和其餘設計模式,請參考這本書:安全
《Cocoa design pattern》atom
背景spa
單例是一種重要的概念,它是一種極其便利的設計模式。在iPhone SDK中大量使用了單例的概念,例如,UIApplication的sharedApplication方法,任什麼時候候都會返回一個當前應用程序的UIApplication實例。.net
將如何實現線程
使用下列代碼實現一個單例類:設計
MyManager.horm
#import<foundation/Foundation.h>對象
@interfaceMyManager : NSObject {開發
NSString *someProperty;
}
@property(nonatomic, retain) NSString *someProperty;
+(id)sharedManager;
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.
}
咱們定義了一個靜態變量叫作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];
}