我到处都看到了单例模式的这种特殊实现:
+ (CargoBay *)sharedManager {
static CargoBay *_sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedManager = [[CargoBay alloc] init];
});
return _sharedManager;
}
它似乎被认为是一种良好的做法(特别是来自CargoBay)。
我唯一不理解的部分是第一行static CargoBay *_sharedManager = nil;
。
为什么要将static
变量设置为nil
?
答案 0 :(得分:8)
这只是一个可读性,惯例和实践的问题。这不是真的需要,因为:
一。它的价值永远不会被检查。在较旧的单例实现中,曾经有着名的
+ (id)sharedInstance
{
static SomeClass *shared = nil;
if (shared == nil)
shared = [[SomeClass alloc] init];
return shared;
}
代码 - 要使这个方法起作用,必须将支持变量初始化为nil,因为如果它第一次不是nil,它将错误地省略if部分中的alloc-init并返回一个垃圾指针。但是,使用GCD解决方案,不再需要nil-check - GCD处理'仅执行此代码一次'编译指示。
两个。但是:静态变量被隐式初始化为零。因此,即使您只是写static id shared;
,它最初也会是nil
。
三。为什么这可能是好的做法?因为,尽管我提到了前两个原因,但让源代码的读者知道某些内容被明确初始化为零仍然更具可读性。或者甚至可能存在一些不符合要求的实现,其中静态变量没有被正确地自动初始化,然后应该采取这种行动。
答案 1 :(得分:1)
您将其设置为nil以确保您获得干净的实例。
这是您想要做的更具可读性的版本:
+ (GlobalVariables *)sharedInstance {
// the instance of this class is stored here
static GlobalVariables *myInstance = nil;
// check to see if an instance already exists
if (nil == myInstance) {
myInstance = [[[self class] alloc] init];
}
// return the instance of this class
return myInstance;
}
但是有大量的帖子显示这可能不是线程安全的,所以转向上面的方法和我发布的方法的混合,你得到这个:
// Declared outside Singleton Manager
static SingletonClass *myInstance = nil;
+ (GlobalVariables *)sharedInstance {
if (nil != myInstance) {
return myInstance;
}
static dispatch_once_t pred; // Lock
dispatch_once(&pred, ^{ // This code is called at most once per app
myInstance = [[GlobalVariables alloc] init];
});
return myInstance;
}