Swift中dispatch_once的示例

Sen*_*ful 13 cocoa swift swift2

是否有一个如何在Swift中使用dispatch_once的例子?(最好是Apple的一个.)

注意:在这种情况下,我不会将它用于单身人士 ; 我想只运行一次任意代码.

更新:我主要对在实例方法中使用它时推荐的约定感兴趣,但是在类方法,函数和全局上下文中的使用对于完整性是有用的.

zrz*_*zka 28

dispatch_once_t是类型别名(Int).标题文档:

/*!
 * @typedef dispatch_once_t
 *
 * @abstract
 * A predicate for use with dispatch_once(). It must be initialized to zero.
 * Note: static and global variables default to zero.
 */
typealias dispatch_once_t = Int
Run Code Online (Sandbox Code Playgroud)

以下是dispatch_once文档中的引用:

谓词必须指向存储在全局或静态范围内的变量.使用带有自动或动态存储的谓词(包括Objective-C实例变量)的结果是未定义的.

令牌变量必须存储在全局/静态范围内,并且必须初始化为零,这导致此代码:

import Foundation

var token: dispatch_once_t = 0
dispatch_once(&token) { () -> Void in
  print("Called once")
}
Run Code Online (Sandbox Code Playgroud)

如果省略= 0(token初始化),它就不起作用,因为尽管statics和globals默认为零,但编译器会在初始化之前产生错误变量'token'的地址.在Xcode 7B2中测试过.


更多基于评论的例子.如果你在class方法内,你有几种可能性.

您不能在方法内部声明静态属性,否则编译器产生静态属性只能在类型错误上声明.这不起作用:

class func doItOnce() {
  static var token: dispatch_once_t = 0
  ...
}
Run Code Online (Sandbox Code Playgroud)

必须在类型上声明.这是在Swift 1.2(Xcode 6.3 IIRC)中引入的.

现在允许在类中使用"静态"方法和属性(作为"类final"的别名).现在,您可以在类中声明静态存储属性,这些属性具有全局存储,并且在首次访问时(例如全局变量)会被懒惰地初始化.协议现在将类型要求声明为"静态"要求,而不是将它们声明为"类"要求.(17198298)

那么,如果我们不喜欢全局变量,我们可以做些什么?

类型上的静态变量

class MyClass {
  private static var token: dispatch_once_t = 0

  class func doItOnce() {
    dispatch_once(&token) {
      print("Do it once")
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

包含在struct中的方法中的静态

不喜欢yur类的静态属性?想在你的方法中拥有它吗?将它包装在struct中,如下所示:

class func doItOnce() {
  struct Tokens { static var token: dispatch_once_t = 0 }
  dispatch_once(&Tokens.token) {
    print("Do it once")
  }
}
Run Code Online (Sandbox Code Playgroud)

实际上我并不知道任何Apple推荐,最佳实践,...如何做到这一点dispatch_once.只需使用您最喜欢的任何东西,对您感觉良好并且只满足标准全局/静态范围.