Skip to content

Instantly share code, notes, and snippets.

@plummer
Last active February 1, 2024 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save plummer/99a21d013de0cfab773028f8507f92d5 to your computer and use it in GitHub Desktop.
Save plummer/99a21d013de0cfab773028f8507f92d5 to your computer and use it in GitHub Desktop.
DispatchGroup convenience wrapper for executing a series of blocks concurrently
import Foundation
extension DispatchGroup {
/// Completes a series of blocks and finally executes a completion handler.
///
/// - Parameters:
/// - label: An optional DispatchQueue label (defaults to bg)
/// - qos: An optional DipatchQos (defaults to background)
/// - blocks: The series of blocks to call.
/// - completion: The final completion handler when all blocks are
/// finished.
///
/// Ensure you call the completion handler in every block.
func complete(
label: String = "bg",
qos: DispatchQoS = .background,
_ blocks: ((() -> Void) -> Void)...,
completion: @escaping () -> Void) {
for block in blocks {
self.enter()
DispatchQueue(
label: label,
qos: qos).async {
block({
self.leave()
})
}
}
self.notify(queue: .main) {
completion()
}
}
}
// MARK: - Example
DispatchGroup().complete(
{ completion in sleep(1); print("execution 1"); completion() },
{ completion in print("execution 2"); completion() },
{ completion in print("execution 3"); completion() }
) {
print("end of group completion handler")
}
@Gargo
Copy link

Gargo commented Jan 31, 2024

shouldn't you store DispatchGroup object somewhere?

@Gargo
Copy link

Gargo commented Jan 31, 2024

and there is a mistake somewhere - if you call completion() inside another completion:

 { completion in
 print("execution 1");
self.someAsyncFunc {
 completion()
}
 }

you will get an error Escaping closure captures non-escaping value

Should I declare "blocks" for example as the following?

_ blocks: (((() -> Void)?) -> Void)...

@plummer
Copy link
Author

plummer commented Jan 31, 2024

Hi Gargo, I recommend using structured concurrency if you are trying to do this in the future. This code is quite old and I wouldn't use it now.

@Gargo
Copy link

Gargo commented Feb 1, 2024

@plummer I still don't understand how structured concurrency works. I have recently read that Task { Task { ... } } is not equal to DispatchQueue.global().async { DispatchQueue.global().async { ... } } and it confuses me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment