Task / TaskGroup / async let
In Swift, a Task represents a unit of asynchronous work. You can create independent tasks or manage dynamic parallel work using withTaskGroup.
Syntax
// Create a new task
Task {
await someAsyncFunction()
}
// Task with priority
Task(priority: .high) {
await importantWork()
}
// Detached task (independent of the current context)
Task.detached {
await backgroundWork()
}
// Task group (dynamic parallel processing)
await withTaskGroup(of: SomeType.self) { group in
group.addTask { await work1() }
group.addTask { await work2() }
for await result in group {
// Process each task's result
}
}
Syntax Reference
| Syntax | Description |
|---|---|
| Task { } | Creates a new asynchronous task. Inherits the current actor context. |
| Task.detached { } | Creates a task that is independent of the current context. |
| Task.cancel() | Cancels the task. |
| Task.isCancelled | Checks whether the task has been cancelled. |
| withTaskGroup(of:) | Creates a task group that manages a dynamic number of parallel tasks. |
| withThrowingTaskGroup(of:) | Creates a task group whose tasks can throw errors. |
| group.addTask { } | Adds a task to the task group. |
Sample Code
import Foundation
// Task cancellation
let task = Task {
for i in 1...10 {
try Task.checkCancellation() // Throws CancellationError if the task has been cancelled
try await Task.sleep(nanoseconds: 100_000_000)
print("Step \(i) complete")
}
}
Task {
try await Task.sleep(nanoseconds: 300_000_000)
task.cancel()
print("Task cancelled")
}
// withTaskGroup: dynamic parallel processing
func fetchAllUsers(ids: [Int]) async -> [String] {
let users = [1: "Alice", 2: "Bob", 3: "Carol", 4: "Dave"]
return await withTaskGroup(of: String?.self) { group in
for id in ids {
group.addTask {
try? await Task.sleep(nanoseconds: 100_000_000)
return users[id]
}
}
var results: [String] = []
for await name in group {
if let name = name {
results.append(name)
}
}
return results
}
}
Task {
let names = await fetchAllUsers(ids: [1, 2, 3, 4, 5])
print("Fetched users: \(names.sorted())")
}
Notes
Use Task to start asynchronous work from top-level or synchronous code. Tasks are cancellable — it is recommended to periodically check Task.checkCancellation() or Task.isCancelled inside long-running operations.
withTaskGroup is suited for dynamic parallel processing, such as processing each element of an array concurrently. It is the right choice when the number of tasks is not known at compile time. Because Task.detached does not inherit the parent actor context, you must explicitly specify @MainActor when updating the UI.
For more on actors, see Actor / Preventing Data Races.
If you find any errors or copyright issues, please contact us.