zsong zsong - 5 months ago 23
Swift Question

How to know all dispatched tasks are completed if use dispatch_after in a loop?

Intuitively, I tried something like this:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
for i in 0..<10 {
CATransaction.begin()

let now = DISPATCH_TIME_NOW
CATransaction.setCompletionBlock {
var delay = dispatch_time(now, 0)
dispatch_after(delay, dispatch_get_main_queue(), {
myfunc()
dispatch_semaphore_signal(semaphore)
})
}

CATransaction.commit()
}

for i in 0..<10 {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}

//task will be executed after 10 jobs are completed.


However, it seem dispatch_semaphore_wait actually blocks dispatch_after from being executed. How to wait until all 10 async jobs are done?

Thanks!

Answer

You should be using dispatch groups as in the following example. Make sure to match the number of enter/leave calls otherwise your code in the notify block will never get executed.

let dispatchGroup = dispatch_group_create()

for _ in 0..<10 {
    dispatch_group_enter(dispatchGroup)

    // Do some async tasks
    let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))

    dispatch_after(delay, dispatch_get_main_queue(), {
        self.myfunc()
        dispatch_group_leave(dispatchGroup)
    })
}

dispatch_group_notify(dispatchGroup, dispatch_get_main_queue()) {
    // The code here will run after all tasks are completed
}