创建单例
背景
很多时候,我们在网上,或者开源项目中,看到类似下面这样创建一个单例:
+(MyClass *)singleton {
static MyClass *shared = nil;
if(shared == nil) {
shared = [[MyClass alloc] init];
}
return shared;
}
但是,上面的代码在很多层面是错误的。首先,它不是线程安全的,当多个线程调用这个创建方法时,我们无法确保正确创建了一个实例,有时在苹果的官方例子中也是这么写的。
如果你必须使用单例,可以使用dispatch_once()
。
dispatch_once()
安全地解决了上面存在的问题:
(1)它保证了在块中的代码将在应用中只调用一次
(2)它是线程安全的
(3)它比使用其他方法创建单例更快,比如使用@synchronize()
@implementation Singleton
static Singleton *shareSingleton = nil;
+(Singleton*) shareInstance {
@synchronized(self){ //加锁
if (shareSingleton == nil) {
shareSingleton = [[Singleton alloc] init];
}
}
return shareSingleton;
}
最佳实践
所以,创建单例的最佳实践应该是:
+(MyClass *)singleton {
static dispatch_once_t pred;
static MyClass *shared = nil;
dispatch_once(&pred, ^{
shared = [[MyClass alloc] init];
});
return shared;
}
总结
在实际项目中,我们应该尽量避免过多使用单例,虽然单例不是什么魔鬼,但是能不用就不用。如果你必须使用单例,也要使用正确的方法来创建它。