Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Created August 12, 2014 16:25
Show Gist options
  • Save kristopherjohnson/7522f92bb5c4b667d506 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/7522f92bb5c4b667d506 to your computer and use it in GitHub Desktop.
Example of using dispatch_once() in Swift
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()
*/
@toohotz
Copy link

toohotz commented Oct 31, 2015

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).

@alickbass
Copy link

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.

@arielelkin
Copy link

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()
*/

@natebird
Copy link

natebird commented Apr 6, 2016

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()
}

@JKalash
Copy link

JKalash commented Jun 29, 2016

How about Swift 3.0? compiler nags about dispatch_once . Says should use lazily initialized globals instead.

@cybercent
Copy link

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
}

@tadassce
Copy link

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