在Swift 3中,是否需要使用dispatch_once? [英] Whither dispatch_once in Swift 3?

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

问题描述

好的,所以我发现了有关Xcode 8中新的 Swifty Dispatch API 的知识. c0>,并且我一直在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的代币时可能会遇到问题.实际上,实际上没有安全的方法来使用没有这种递归,因此他们摆脱了它,而只是使用构建在其上的语言功能:

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天全站免登陆