Waiting until the task finishes
Use DispatchGroup
s to achieve this. You can either get notified when the group's enter()
and leave()
calls are balanced:
func myFunction() { var a: Int? let group = DispatchGroup() group.enter() DispatchQueue.main.async { a = 1 group.leave() } // does not wait. But the code in notify() gets run // after enter() and leave() calls are balanced group.notify(queue: .main) { print(a) }}
or you can wait:
func myFunction() { var a: Int? let group = DispatchGroup() group.enter() // avoid deadlocks by not using .main queue here DispatchQueue.global(attributes: .qosDefault).async { a = 1 group.leave() } // wait ... group.wait() print(a) // you could also `return a` here}
Note: group.wait()
blocks the current queue (probably the main queue in your case), so you have to dispatch.async
on another queue (like in the above sample code) to avoid a deadlock.
In Swift 3, there is no need for completion handler when DispatchQueue
finishes one task. Furthermore you can achieve your goal in different ways
One way is this:
var a: Int? let queue = DispatchQueue(label: "com.app.queue") queue.sync { for i in 0..<10 { print("Ⓜ️" , i) a = i } } print("After Queue \(a)")
It will wait until the loop finishes but in this case your main thread will block.
You can also do the same thing like this:
let myGroup = DispatchGroup() myGroup.enter() //// Do your task myGroup.leave() //// When your task completes myGroup.notify(queue: DispatchQueue.main) { ////// do your remaining work }
One last thing: If you want to use completionHandler when your task completes using DispatchQueue, you can use DispatchWorkItem
.
Here is an example how to use DispatchWorkItem
:
let workItem = DispatchWorkItem { // Do something}let queue = DispatchQueue.global()queue.async { workItem.perform()}workItem.notify(queue: DispatchQueue.main) { // Here you can notify you Main thread}
Swift 5 version of the solution
func myCriticalFunction() { var value1: String? var value2: String? let group = DispatchGroup() group.enter() //async operation 1 DispatchQueue.global(qos: .default).async { // Network calls or some other async task value1 = //out of async task group.leave() } group.enter() //async operation 2 DispatchQueue.global(qos: .default).async { // Network calls or some other async task value2 = //out of async task group.leave() } group.wait() print("Value1 \(value1) , Value2 \(value2)") }