当我使用static来实现singleton时,有什么可能出错的地方吗



我正在实现一个单例类(如果这是错误的,我们就不要参与讨论)。我有一个方法来获取这个类的实例,它被延迟初始化:

+ (FFDataManager *)sharedDataManager {
  static FFDataManager *dm = nil;
  if (!dm) {
    dm = [[FFDataManager alloc] init];
  }
  return dm;
}

当使用static(方法内部)而不是创建全局变量时,我应该注意什么吗?有什么可能出错的吗?互联网上的所有教程都使用了一个全局变量。

我喜欢的单例实现看起来像:

+ (MyClass *) sharedInstance {
    static dispatch_once_t predicate = 0;
    __strong static MyClass *shared = nil;
    dispatch_once(&predicate, ^{
        shared = [[self alloc] init];
    });
    return shared;
}

使用dispatch_once可以确保这也是线程安全的。当多个线程同时访问时,您的代码将分配两次。

要回答最初的问题(其他人已经解决了进行初始化的最佳方法):

当使用静态(方法内部)而不是创建全局变量时,我应该注意什么吗?

没有。

区别在于可见性寿命

  • 全局(带或不带静态)生存期是应用程序执行的生存期
  • 在整个应用程序中,不带static的全局可见。通过在extern语句中命名它,可以从其他任何地方引用它
  • 带有static的全局仅在包含的编译单元中可见(通常是单个文件,但#import/#include可以更改这一点)
  • 在函数/方法中声明为static的变量是一个全局变量,在该函数/方法内只有可见

如果你只在一个函数中使用全局,那么你所做的是好的——它将可见性限制在需要的地方,同时保持执行寿命。任何初始值设定项都会运行一次,就像文件级全局变量一样。

您创建的是一个静态局部变量。静态局部变量通过连续的方法调用保持其值。只能从定义它们的方法中访问它们。当应用程序启动时,静态局部变量被设置为0一次。

因此,在我看来,每次调用sharedDataManager时,都要声明一个新的静态局部变量,并将其设置为nil。我认为这没有必要,甚至没有好处。而且每次if (!dm)检查dm时都是nil,因为您在前面将dm设置为零。

我会采用静态全局方法。

编辑:看看http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/

最新更新