Swift 3 中的 dispatch_once 在哪里? [英] Whither dispatch_once in Swift 3?

查看:24
本文介绍了Swift 3 中的 dispatch_once 在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我在 Xcode 8 中发现了新的 Swifty Dispatch API.我很高兴使用 DispatchQueue.main.async,我一直在浏览 Xcode 中的 Dispatch 模块以找到所有新的 API.

Okay, so I found out about the new Swifty Dispatch API in Xcode 8. I'm having fun using DispatchQueue.main.async, and I've been browsing around the Dispatch module in Xcode to find all the new APIs.

但我也使用 dispatch_once 来确保诸如单例创建和一次性设置之类的事情不会被执行多次(即使在多线程环境中)...和 ​​dispatch_once 在新的 Dispatch 模块中找不到?

But I also use dispatch_once to make sure that things like singleton creation and one-time setup don't get executed more than once (even in a multithreaded environment)... and dispatch_once is nowhere to be found in the new Dispatch module?

static var token: dispatch_once_t = 0
func whatDoYouHear() {
    print("All of this has happened before, and all of it will happen again.")
    dispatch_once(&token) {
        print("Except this part.")
    }
}

推荐答案

从 Swift 1.x 开始,Swift 一直在使用 dispatch_once 幕后 执行全局变量和静态属性的线程安全延迟初始化.

Since Swift 1.x, Swift has been using dispatch_once behind the scenes to perform thread-safe lazy initialization of global variables and static properties.

所以上面的 static var 已经在使用 dispatch_once,这使得它有点奇怪(并且可能再次使用它作为另一个 dispatch_once 的标记).事实上,没有这种递归的使用 dispatch_once 真的没有安全的方法,所以他们摆脱了它.相反,只需使用基于它构建的语言特性:

So the static var above was already using dispatch_once, which makes it sort of weird (and possibly problematic to use it again as a token for another dispatch_once. In fact there's really no safe way to use dispatch_once without this kind of recursion, so they got rid of it. Instead, just use the language features built on it:

// global constant: SomeClass initializer gets called lazily, only on first use
let foo = SomeClass()

// global var, same thing happens here
// even though the "initializer" is an immediately invoked closure
var bar: SomeClass = {
    let b = SomeClass()
    b.someProperty = "whatever"
    b.doSomeStuff()
    return b
}()

// ditto for static properties in classes/structures/enums
class MyClass {
    static let singleton = MyClass()
    init() {
        print("foo")
    }
}

所以,如果您一直使用 dispatch_once 进行一次性初始化,从而产生某个值,那就太好了——您可以将该值设为全局变量或您正在初始化的静态属性.

So that's all great if you've been using dispatch_once for one-time initialization that results in some value -- you can just make that value the global variable or static property you're initializing.

但是如果您使用 dispatch_once 来完成不一定有结果的工作怎么办?您仍然可以使用全局变量或静态属性来做到这一点:只需将该变量的类型设为 Void:

But what if you're using dispatch_once to do work that doesn't necessarily have a result? You can still do that with a global variable or static property: just make that variable's type Void:

let justAOneTimeThing: () = {
    print("Not coming back here.")
}()

如果访问全局变量或静态属性来执行一次性工作对您来说并不合适——比如说,您希望您的客户在使用您的库之前调用初始化我"函数——只需将该访问权限包装在一个函数中:

And if accessing a global variable or static property to perform one-time work just doesn't feel right to you -- say, you want your clients to call an "initialize me" function before they work with your library -- just wrap that access in a function:

func doTheOneTimeThing() {
    justAOneTimeThing
}

有关更多信息,请参阅迁移指南.

See the migration guide for more.

这篇关于Swift 3 中的 dispatch_once 在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆