OC的单例模式
原文: http://www.galloway.me.uk/tutorials/singleton-classes/
在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_t onceToken; 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方法只会被创建一次。这是线程安全的,你无需担心什么。
但是,如果你不想用GCD,也可以这样实现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