4

我到处都看到了单例模式的这种特殊实现:

+ (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

4

2 回答 2

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.

三。为什么这可能是一个好习惯?因为,尽管我提到了前两个原因,但让源代码的读者知道某些东西被显式初始化为零仍然更具可读性。或者甚至可能存在一些不符合要求的实现,其中静态变量没有正确地自动初始化,然后应该采取这个行动。

于 2012-09-22T15:03:13.053 回答
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;
}
于 2012-09-22T15:08:20.933 回答