When keeping track of various pieces of information in a variable when using a dispatch group, I've fallen into a pattern of protecting the variable using a serial queue, and then ultimately notifying on that queue to do something with the final value. Is there a more idiomatic way to protect things?

Here's an example of what I mean that can be run in a Playground:

import Foundation

func uploadAll() {
    func mockUpload(_ delay: TimeInterval, _ queue: DispatchQueue = DispatchQueue(label: "mockUpload", attributes: .concurrent), block: @escaping () -> Void) {
        let deadline = DispatchTime.now() + delay
        queue.asyncAfter(deadline: deadline, execute: block)

    let resultQueue = DispatchQueue(label: "resultQueue")
    var results: [Int] = []

    let group = DispatchGroup()

    for i in 0..<5 {
        mockUpload(TimeInterval(Int.random(in: 1...3))) {
            resultQueue.async {

    group.notify(queue: resultQueue) {
        print("results: \(results)")
        DispatchQueue.main.async {
            // And maybe do something on the main queue...


import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.