Leave a rating/review
What if you need to call an asynchronous function as part of the group? How can you tell the group when it really finishes?
Open the starter playground. Here’s some code that wraps the slowAdd(_:) function as an asynchronous function:
func asyncAdd(
_ input: (Int, Int),
runQueue: DispatchQueue = DispatchQueue.global(qos: .userInitiated),
completionQueue: DispatchQueue = DispatchQueue.main,
completion: @escaping (Result<Int, SlowAddError>) -> ()) {
runQueue.async {
let result = slowAddPlus(input)
completionQueue.async { completion(result) }
}
}
The parameters include run and completion queues with default values and a completion handler, which you’ll supply when you call this function.
Now, you’re going to wrap this asyncAdd function, using the same argument list, and add a dispatchGroup argument. First, copy the signature of func asyncAdd, change its name, and add a group argument:
func asyncAdd_Group(
_ input: (Int, Int),
runQueue: DispatchQueue = DispatchQueue.global(qos: .userInitiated),
completionQueue: DispatchQueue = DispatchQueue.main,
group: DispatchGroup,
completion: @escaping (Result<Int, SlowAddError>) -> ()) {
}
Inside this asyncAdd_Group function, call asyncAdd, passing the matching arguments:
asyncAdd(input) { result in
completionQueue.async { completion(result) }
}
To hook this up with the dispatch group, call the dispatch group’s enter method before you call asyncAdd:
group.enter()
And defer its leave method in asyncAdd’s completion handler:
defer { group.leave() } // add this line
completionQueue.async { completion(result) } // already written
This balanced pair of enter and leave calls tells the dispatch group when this asynchronous function starts and finishes. When it finishes, the group can check it off its list of tasks. Using defer ensures the task leaves the group even if it fails.
Now, you get to use your new asynchronous group function. You already have this dispatch group called wrappedGroup. And now you’ll create a group of asyncAdd_Group tasks:
for pair in numberArray {
asyncAdd_Group(pair, group: wrappedGroup) { result in // provide completion argument
print("Result = \(result)")
}
}
For each pair of Ints in numberArray: the input is pair. You’ll run the work on asyncAdd’s default run and completion queues. And the group is wrappedGroup.
The whole point of a dispatch group is to do something when all the tasks finish, so write the notify handler:
wrappedGroup.notify(queue: DispatchQueue.main) {
print("WRAPPED ASYNC ADD: Completed all tasks")
sleep(1)
PlaygroundPage.current.finishExecution()
}
Run the playground:
=== Group of async tasks ===
Result = success(9)
Result = success(1)
Result = success(5)
Result = success(17)
Result = failure(WrapAsyncMethod_Sources.SlowAddError.notEnoughFingers)
WRAPPED ASYNC ADD: Completed all tasks
slowAddPlus flips a coin to decide whether to return success or failure.
Now you know how to wrap an asynchronous function to add to a dispatch group. Next, you’ll apply this knowledge to wrap URLSession dataTask.