Using a dispatch_once singleton model in Swift
Asked 07 September, 2021
Viewed 1.8K times
  • 53
Votes

I'm trying to work out an appropriate singleton model for usage in Swift. So far, I've been able to get a non-thread safe model working as:

class var sharedInstance: TPScopeManager {
    get {
        struct Static {
            static var instance: TPScopeManager? = nil
        }

        if !Static.instance {
            Static.instance = TPScopeManager()
        }

        return Static.instance!
    }
}

Wrapping the singleton instance in the Static struct should allow a single instance that doesn't collide with singleton instances without complex naming schemings, and it should make things fairly private. Obviously though, this model isn't thread-safe. So I tried to add dispatch_once to the whole thing:

class var sharedInstance: TPScopeManager {
    get {
        struct Static {
            static var instance: TPScopeManager? = nil
            static var token: dispatch_once_t = 0
        }

        dispatch_once(Static.token) { Static.instance = TPScopeManager() }

        return Static.instance!
    }
}

But I get a compiler error on the dispatch_once line:


  

Cannot convert the expression's type 'Void' to type '()'

I've tried several different variants of the syntax, but they all seem to have the same results:

dispatch_once(Static.token, { Static.instance = TPScopeManager() })

What is the proper usage of dispatch_once using Swift? I initially thought the problem was with the block due to the () in the error message, but the more I look at it, the more I think it may be a matter of getting the dispatch_once_t correctly defined.

30 Answer