单例模式可以说是每个应用都有用到的一个模式,在iOS的世界里更是常见。例如我们的UIApplication sharedApplicaiton应用的就是单利模式, defaultManager和defaultCenter等也是常见的单利。这也是为什么人们经常把CoreData的实例变量放在UIApplication里面。
对单例有了更清楚的了解以后,我们可以让我们的代码更加清晰。比如,我们可以把放在AppDelegate里的关于CoreData的代码移植到其他的单例类里面。
在相关网络博客上面看到了下面三种实现单利的方法。
1. 使用GCD实现单线程实现(给一篇参考文章)
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词,第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全。
@implementation MyClass#pragma mark Singleton Methods+ (id)sharedClass { static MyClass *sharedMyClass = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedMyClass = [[self alloc] init]; }); return sharedMyClass;}@end2. 加上同步
+ (id)sharedClass { static MyClass *sharedMyClass = nil; @synchronized(self) { if (sharedMyClass == nil) sharedMyClass = [[self alloc] init]; } return sharedMyClass;}
3. 没有ARC的同步实现(官网给出的也是这种方式 )
+ (id)sharedClass { @synchronized(self) { if(sharedMyClass == nil) sharedMyClass = [[super allocWithZone:NULL] init]; } return sharedMyClass;}+ (id)allocWithZone:(NSZone *)zone { return [[self sharedMyClass] retain];}- (id)copyWithZone:(NSZone *)zone { return self;}- (id)retain { return self;}- (unsigned)retainCount { return UINT_MAX;}- (oneway void)release { // never release}- (id)autorelease { return self;}4. 其实还有其他的方式来实现。比如你将同步的代码快写到一个SynthesizeSingleton.h的头文件里。
#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \\static classname *shared##classname = nil; \\+ (classname *)shared##classname \{ \ @synchronized(self) \ { \ if (shared##classname == nil) \ { \ shared##classname = [[self alloc] init]; \ } \ } \ \ return shared##classname; \} \\+ (id)allocWithZone:(NSZone *)zone \{ \ @synchronized(self) \ { \ if (shared##classname == nil) \ { \ shared##classname = [super allocWithZone:zone]; \ return shared##classname; \ } \ } \ \ return nil; \} \\- (id)copyWithZone:(NSZone *)zone \{ \ return self; \} \\在相关的类
@interface Preference : NSObject+ (Preference *)sharedPreference;
在类的实现里加上
#import "SynthesizeSingleton.h"@implementation PreferenceSYNTHESIZE_SINGLETON_FOR_CLASS(Preference);
这种方式无疑是最简单也最易复用的方式。使用的时候直接调用shareXxx就可以了。