Whither dispatch_once in Swift 3?
grand-central-dispatch, libdispatch, swift, swift3
Solution
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.
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")
}
}
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.
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.
Problem
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. 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.") } } ```