Marvin K. Bellamy
Marvin K. Bellamy

Reputation: 13

How do you wait on a main queue completion handler?

What I'm trying to do is sequentially execute a for loop where I wait for the completionHandler() before starting the next iteration.

Code:

// we're on the main queue
for index in 0..<count {
    var outcome: Any?
    let semaphore = DispatchSemaphore(value: 0)
    let queue = DispatchQueue(label: "\(index) iteration")
    // this will access a UI component and wait for user to
    // enter a value that's passed to the completion handler
    funcWithCompletionHandler() { [weak self] (result) in
        outcome = result
        semaphore.signal()
    }
    // wait here for the completion handler to signal us
    queue.sync {
        semaphore.wait()
        if let o = outcome {
            handleOutcome(outcome)
        }
    }
    // now, we iterate
}

I've tried a lot of other solutions I see here, nothing seems to work.

Upvotes: 1

Views: 487

Answers (1)

Gustavo Vollbrecht
Gustavo Vollbrecht

Reputation: 3256

I prefer working with a background group, you can make an instance of it on your class like this: var group = DispatchGroup()

    DispatchQueue.global(qos: .background).async {
        self.group.wait()

       // this part will execute after the last one left
       // .. now, we iterate part
    }


    for index in 0..<count {
        var outcome: Any?
        let queue = DispatchQueue(label: "\(index) iteration")



        funcWithCompletionHandler() { [weak self] (result) in
            if let strongSelf = self {
                outcome = result
                strongSelf.group.enter() // group count = 1
            }

        }

        queue.sync {
            if let o = outcome {
                handleOutcome(outcome)
                self.group.leave()
                // right here group count will be 0 and the line after wait will execute
            }
        }
    }

Upvotes: 1

Related Questions