【问题标题】:Why is this code WORKING?为什么这段代码有效?
【发布时间】:2014-02-02 02:09:21
【问题描述】:

Matt Galloway 建议这是初始化单例的正确方法:

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}

我已经测试过,它可以正常工作,但我不明白为什么。首次创建单例时,变量 sharedMyManager 设置为 init 行的内容,但是当已经创建单例并且我使用 [MySingleton sharedManager]; 访问它时,代码的第一行运行,将 sharedMyManager 设置为 @987654327 @ 然后最后一行运行返回理论上 nil 的内容。事实上,它返回的是正确的单例,但为什么呢?

如果 nil 设置为 nilsharedMyManager 如何返回正确的对象?

注意,因为在创建单例之后,我正在与sharedManager 的后续调用交谈。

我想 static 关键字正在发挥作用,现在允许多次分配值,但如果这是真的,那么 init 部分不应该工作,因为静态变量首先被分配给 nil .

请解释一下,因为我才五岁。谢谢。

【问题讨论】:

  • 你怎么知道 sharedMyManager 被设置为 nil (在第一次之后)?也许它只是进入静态声明,意识到 sharedMyManager 存在并继续运行......就在“return sharedMyManager”运行之前,它的值是什么?
  • 提示:何时 dispatch_once 运行提供给它的块?该块在运行时会立即对静态变量产生副作用(并且保证运行一次[通过dispatch_once 和静态onceToken sentinel],并且仅在从该方法第一次返回之前运行一次)。
  • 就“魔术”static 修饰符而言:它有效地使变量成为持久的全局变量 - 只能从该方法上下文访问。这种static 变量的初始化发生在方法被调用之前。如果你要写static MyManager *sharedMyManager; sharedMyManager = nil; 那么赋值 - 不是初始化! - 每次都会发生。
  • @user2864740 - 我说的是对该方法的后续调用,而不是第一次。

标签: ios objective-c cocoa-touch singleton


【解决方案1】:

dispatch_once() 将类实例化一次。

所以在调用 sharedManager() 一次之后,单例已经存在,并且可以重复使用。

【讨论】:

  • 好的,但我说的是对该方法的后续调用,而不是第一次。如果你看一下这个方法,每次调用 sharedManager 时,它都会将 sharedMyManager 设置为 nil,然后返回 sharedMyManager,它应该是 nil,但它不是。
【解决方案2】:

sharedMyManager 是一个静态变量,因此根据定义,它的初始化程序只会运行一次。第一次(仅)输入块时,它被设置为nil。然后dispatch_once块运行并分配它,然后sharedMyManager被返回。

对于所有后续调用,nil 的初始化不会发生dispatch_once() 的内容也不会重新执行,因此实际上所有发生的只是初始化变量的返回。 p>

【讨论】:

  • 因此将其设置为 nil 不算作初始化。我是这么怀疑的。只需要确认。谢谢!
  • 没问题。这是一个你可能会觉得有用的 SO 线程:stackoverflow.com/questions/5567529/…
  • 是的,将其设置为零确实算作初始化。因为它是静态的,所以无论如何它都会被初始化为零,但关键是初始化代码(即,它被赋值为 nil 的地方)只会发生一次。幕后的编译器确保第一次赋值只发生一次。
猜你喜欢
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
  • 2012-11-04
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
相关资源
最近更新 更多