单例模式 是我在iOS开发中使用的最多的设计模式之一。它是一种不需要你去手动传递,而能在 代码的不同部分之间分享数据的一种极其强大的方式。关于单例模式和其他设计模式的更多 详情,可参考这一本不错的书:
背景 单例类是一个需要重点去理解的概念,因为它展示了一种非常有用的设计模式。这种设计思想被广泛应用在了iPhone SDK当中,例如:在代码的任何地方给UIApplication发一个叫做sharedApplication的消息都会返回同一个和当前正在运行的程序相关的UIApplicition实例。
怎么实现 可以在Objctive-C中使用如下代码来实现一个单例类:
1 2 3 4 5 6 7 8 9 10 11 #import <foundation/Foundation.h> @interface MyManager : NSObject { NSString *someProperty; } @property (nonatomic , retain) NSString *someProperty;+ (id )sharedManager; @end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #import "MyManager.h" @implementation MyManager @synthesize someProperty;#pragma mark 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 { } @end
上面的代码所做的是在sharedManager方法中定义一个名为sharedMyManager的静态局部变量(仅仅在这一个translation unit 中是全局的),这个静态局部变量仅仅初始化一次。为了确保它只被建立一次,我们使用了Grand Central Dispatch(GCD) 中的dispath_once .GCD是完全由操作系统控制的,并且是线程安全的,所以你可以毫无顾虑的去使用它.如果不愿使用GCD,可以使用以下代码来替换sharedManager:
1 2 3 4 5 6 7 8 + (id )sharedManager { static MyManager *sharedMyManager = nil ; @synchronized (self ) { if (sharedMyManager == nil ) sharedMyManager = [[self alloc] init]; } return sharedMyManager; }
然后,你就可以在工程的任意地方通过调用如下的函数来饮用一个单例类:
MyManager *sharedManager = [MyManager sharedManager];我已经在代码中大量使用了这样的方式,比如:创建一个单例类去控制CoreLocation或者CoreData函数
Non-ARC code 不推荐使用。但是如果你没有使用Automatic Reference Counting(ARC) 的话,只能使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #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 ; } - (oneway void )release { } - (id )autorelease { return self ; } - (id )init { if (self = [super init]) { someProperty = [[NSString alloc] initWithString:@"Default Property Value" ]; } return self ; } - (void )dealloc { [someProperty release]; [super dealloc]; } @end
原文在此