Search code examples
iosswiftgrand-central-dispatchswift5idioms

What's the most "Swift-like"/clean way to set a non-nil value with a sync DispatchQueue?


I have a synchronous, concurrent DispatchQueue that I'm using to grab a value, so that way it will be available immediately in the control flow.

let isEmpty: Bool

dispatchQueue.sync {
    isEmpty = self.myProtectedArray.isEmpty
}

print(isEmpty) // error

Even though by the print statement isEmpty will always be assigned a value (due to being synchronous) the Swift compiler does NOT like this.

How should I modify it to be acceptable to the Swift compiler while not being a gross solution? Starting with var isEmpty: Bool = true seems stupid because the "initial value" is unclear.


Solution

  • The synchronous DispatchQueue method

    func sync<T>(execute work: () throws -> T) rethrows -> T
    

    returns the result of the work item to the caller, which mean that you can assign that as the initialization value to the boolean constant:

    let isEmpty = dispatchQueue.sync {
        return self.myProtectedArray.isEmpty
    }
    
    print(isEmpty) // Compiler happy!
    

    As @Rob said, the self. is not needed because the closure is not escaping, and the return keyword can be omitted in the case of a single-expression closure:

    let isEmpty = dispatchQueue.sync {
        myProtectedArray.isEmpty
    }