Swift Task Groups
A task group runs several child tasks together inside one scope. The group collects every child result before the scope finishes.
Adding results inside one group
Each child task returns one number multiplied by ten. The loop adds the returned numbers, so the total stays the same in any finishing order.
let total = await withTaskGroup(of: Int.self) { group in
for number in [1, 2, 3] {
group.addTask {
number * 10
}
}
var sum = 0
for await value in group {
sum += value
}
return sum
}
print(total)Collecting results into a dictionary
Each child task returns a key paired with a squared value. The loop stores each pair in a dictionary, and the final print walks the sorted keys.
let scores = await withTaskGroup(of: (Int, Int).self) { group in
for number in [3, 1, 2] {
group.addTask {
(number, number * number)
}
}
var collected: [Int: Int] = [:]
for await (key, value) in group {
collected[key] = value
}
return collected
}
for key in scores.keys.sorted() {
print("\(key) squared is \(scores[key] ?? 0)")
}A throwing group with a caught error
One child task throws when its number is zero. The catch block prints one fixed message, so the output never depends on finishing order.
enum LoadError: Error {
case empty
}
func load(number: Int) throws -> Int {
if number == 0 {
throw LoadError.empty
}
return number * 10
}
do {
let total = try await withThrowingTaskGroup(of: Int.self) { group in
for number in [2, 0, 3] {
group.addTask {
try load(number: number)
}
}
var sum = 0
for try await value in group {
sum += value
}
return sum
}
print(total)
} catch {
print("Load failed")
}Example
let lengths = await withTaskGroup(of: Int.self) { group in
for word in ["swift", "code", "task"] {
group.addTask {
word.count
}
}
var collected: [Int] = []
for await value in group {
collected.append(value)
}
return collected.sorted()
}
for length in lengths {
print(length)
}Key points
- A task group opens with withTaskGroup and names the type each child task returns.
- The addTask method adds one child task to the group.
- A for await loop reads child results as the tasks finish.
- Child tasks finish in an order the program does not control.
- Collecting results into a dictionary or an array keeps the stored set complete.
- Sorting collected results before printing gives output in a fixed order.
- The withThrowingTaskGroup form lets a child task throw an error.
In this example, each child task returns the count of one word. The collected counts sort into 4, 4, and 5 before printing. Sorting removes any link between finishing order and printed order.
Note
A group scope ends only after every child task has finished.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why does a task group program sort collected results before printing them?