Created
August 12, 2014 16:25
-
-
Save kristopherjohnson/7522f92bb5c4b667d506 to your computer and use it in GitHub Desktop.
Example of using dispatch_once() in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
var token: dispatch_once_t = 0 | |
func test() { | |
dispatch_once(&token) { | |
println("This is printed only on the first call to test()") | |
} | |
println("This is printed for each call to test()") | |
} | |
for _ in 0..<4 { | |
test() | |
} | |
/* Output: | |
This is printed only on the first call to test() | |
This is printed for each call to test() | |
This is printed for each call to test() | |
This is printed for each call to test() | |
This is printed for each call to test() | |
*/ |
BTW, if we take a good look at the documentation https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/
Apple says that variables of this dispatch_once_t must have global or static scope. The result of using this type with automatic or dynamic allocation is undefined.
I don't understand why that code makes sense! The token is a variable, and nothing guarantees it won't be reset:
var token: dispatch_once_t = 0
func test() {
dispatch_once(&token) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
test()
token = 0
test()
/* Output:
This is printed only on the first call to test()
This is printed for each call to test()
This is printed only on the first call to test()
This is printed for each call to test()
*/
The Swift 2.x version of this should look like the following:
import Foundation
struct Static {
static var dispatchOnceToken: dispatch_once_t = 0
}
func test() {
dispatch_once(&Static.dispatchOnceToken) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
for _ in 0..<4 {
test()
}
How about Swift 3.0? compiler nags about dispatch_once . Says should use lazily initialized globals instead.
Swift 3 extension:
import Foundation
public extension DispatchQueue {
private static var _onceTracker = [String]()
public class func once(token: String, block:(Void)->Void) {
objc_sync_enter(self); defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
}
Usage:
DispatchQueue.once(token: "your-unique-token") {
// code to run once
}
In Swift 3 something like this:
class Test {
static let once: Void = {
print("only first time")
}()
func hi() {
Test.once
print("every time")
}
}
let test = Test()
for i in 0..<3 {
test.hi()
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Not necessarily totally wrong but as @jereme pointed out, this will execute every instantiation. @skyluca Static struct is the way to go for Swift 2.0 (similar to how Singleton's are done now as well).