
Swift Concurrency
- 354 installs
- 297 repo stars
- Updated August 4, 2026
- vabole/apple-skills
swift-concurrency is an Apple-platform agent skill that supplies local Swift Concurrency API references for async/await, Task, actors, and AsyncStream for developers who need thread-safe iOS and macOS network and persist
About
swift-concurrency is a vabole/apple-skills reference package for Swift structured concurrency. It ships 7 downloaded markdown files covering Task, TaskGroup, Actor, AsyncSequence, AsyncStream, CheckedContinuation, and a concurrency overview index agents can grep locally before fetching sosumi.ai mirrors. The skill runs in a forked Explore agent context and instructs agents to search local docs first, then sibling Apple skills, then pull additional pages from developer.apple.com via sosumi.ai paths. Developers reach for swift-concurrency when refactoring callback-based network calls to async/await, isolating mutable state with actors, or bridging legacy APIs with continuations without data races.
- Models async networking with URLSession and continuations
- Uses actors to isolate mutable shared state safely
- Applies structured concurrency and task cancellation
- Avoids MainActor violations in SwiftUI updates
- Diagnoses race conditions and priority inversion risks
Swift Concurrency by the numbers
- 354 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #357 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vabole/apple-skills --skill swift-concurrencyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 354 |
|---|---|
| repo stars | ★ 297 |
| Last updated | August 4, 2026 |
| Repository | vabole/apple-skills ↗ |
How do you use Swift actors safely?
Apply Swift concurrency—async/await, actors, and structured tasks—to network calls, persistence, and thread-safe iOS app logic without data races.
Who is it for?
iOS and Apple-platform developers implementing async/await networking, persistence, and actor-isolated state who want grep-friendly local concurrency docs in the agent.
Skip if: Android or cross-platform Kotlin developers, or SwiftUI layout work better served by the companion swiftui skill.
When should I use this skill?
User asks about Swift async/await, actor isolation, TaskGroup parallelism, AsyncStream, or CheckedContinuation bridging in Apple app code.
What you get
Thread-safe async Swift code using Task, TaskGroup, Actor isolation, AsyncStream pipelines, and CheckedContinuation bridges.
- async/await refactored Swift code
- actor-isolated type implementations
By the numbers
- 7 downloaded local reference markdown files for Swift Concurrency APIs
Files
Swift Concurrency Reference
Structured concurrency, actors, and async sequences in Swift.
Downloaded Reference Files
| File | Content |
|---|---|
| concurrency-overview.md | Swift concurrency index |
| task.md | Task struct |
| taskgroup.md | TaskGroup for parallel work |
| actor.md | Actor protocol |
| asyncsequence.md | AsyncSequence protocol |
| asyncstream.md | AsyncStream |
| checkedcontinuation.md | CheckedContinuation for bridging |
Fetching More Docs
1. Search this skill's local .md files first. 2. If the topic is not here, check the other installed Apple skills you have available by their names, descriptions, or SKILL.md frontmatter, then grep their local files. This is faster and uses less context than fetching new docs from the internet. 3. If no installed skill has the page, use the relevant documentation path from concurrency-overview.md with the sosumi.ai Markdown mirror. For example, /documentation/swift/task maps to https://sosumi.ai/documentation/swift/task.
Navigation: Swift
Protocol
Actor
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
Common protocol to which all actors conform.
protocol Actor : AnyObject, SendableOverview
The Actor protocol generalizes over all actor types. Actor types implicitly conform to this protocol.
Actors and SerialExecutors
By default, actors execute tasks on a shared global concurrency thread pool. This pool is shared by all default actors and tasks, unless an actor or task specified a more specific executor requirement.
It is possible to configure an actor to use a specific SerialExecutor, as well as impact the scheduling of default tasks and actors by using a TaskExecutor.
See Also: SerialExecutor
See Also: TaskExecutor
Inherits From
Conforming Types
Instance Properties
- unownedExecutor Retrieve the executor for this actor as an optimized, unowned reference.
Instance Methods
- assertIsolated(_:file:line:)) Stops program execution if the current task is not executing on this actor’s serial executor.
- assumeIsolated(_:file:line:)) Assume that the current task is executing on this actor’s serial executor, or stop program execution otherwise.
- preconditionIsolated(_:file:line:)) Stops program execution if the current task is not executing on this actor’s serial executor.
- withSerialExecutor(_:)-4ff11) Perform an operation with the actor’s SerialExecutor.
- withSerialExecutor(_:)-4ucv5) Perform an operation with the actor’s SerialExecutor.
Actors
- Sendable A thread-safe type whose values can be shared across arbitrary concurrent contexts without introducing a risk of data races.
- AnyActor Common marker protocol providing a shared “base” for both (local)
Actorand (potentially remote)DistributedActortypes. - MainActor A singleton actor whose executor is equivalent to the main dispatch queue.
- GlobalActor A type that represents a globally-unique actor that can be used to isolate various declarations anywhere in the program.
- SendableMetatype A type whose metatype can be shared across arbitrary concurrent contexts without introducing a risk of data races.
- ConcurrentValue
- UnsafeSendable A type whose values can safely be passed across concurrency domains by copying, but which disables some safety checking at the conformance site.
- UnsafeConcurrentValue
- isolation()) Produce a reference to the actor to which the enclosing code is isolated, or
nilif the code is nonisolated. - extractIsolation(_:))
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
Protocol
AsyncSequence
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
A type that provides asynchronous, sequential, iterated access to its elements.
protocol AsyncSequence<Element, Failure>Overview
An AsyncSequence resembles the Sequence type — offering a list of values you can step through one at a time — and adds asynchronicity. An AsyncSequence may have all, some, or none of its values available when you first use it. Instead, you use await to receive values as they become available.
As with Sequence, you typically iterate through an AsyncSequence with a for await-in loop. However, because the caller must potentially wait for values, you use the await keyword. The following example shows how to iterate over Counter, a custom AsyncSequence that produces Int values from 1 up to a howHigh value:
for await number in Counter(howHigh: 10) {
print(number, terminator: " ")
}
// Prints "1 2 3 4 5 6 7 8 9 10 "An AsyncSequence doesn’t generate or contain the values; it just defines how you access them. Along with defining the type of values as an associated type called Element, the AsyncSequence defines a makeAsyncIterator() method. This returns an instance of type AsyncIterator. Like the standard IteratorProtocol, the AsyncIteratorProtocol defines a single next() method to produce elements. The difference is that the AsyncIterator defines its next() method as async, which requires a caller to wait for the next value with the await keyword.
AsyncSequence also defines methods for processing the elements you receive, modeled on the operations provided by the basic Sequence in the standard library. There are two categories of methods: those that return a single value, and those that return another AsyncSequence.
Single-value methods eliminate the need for a for await-in loop, and instead let you make a single await call. For example, the contains(_:) method returns a Boolean value that indicates if a given value exists in the AsyncSequence. Given the Counter sequence from the previous example, you can test for the existence of a sequence member with a one-line call:
let found = await Counter(howHigh: 10).contains(5) // trueMethods that return another AsyncSequence return a type specific to the method’s semantics. For example, the .map(_:) method returns a AsyncMapSequence (or a AsyncThrowingMapSequence, if the closure you provide to the map(_:) method can throw an error). These returned sequences don’t eagerly await the next member of the sequence, which allows the caller to decide when to start work. Typically, you’ll iterate over these sequences with for await-in, like the base AsyncSequence you started with. In the following example, the map(_:) method transforms each Int received from a Counter sequence into a String:
let stream = Counter(howHigh: 10)
.map { $0 % 2 == 0 ? "Even" : "Odd" }
for await s in stream {
print(s, terminator: " ")
}
// Prints "Odd Even Odd Even Odd Even Odd Even Odd Even "Conforming Types
- AsyncCompactMapSequence
- AsyncDropFirstSequence
- AsyncDropWhileSequence
- AsyncFilterSequence
- AsyncFlatMapSequence
- AsyncMapSequence
- AsyncPrefixSequence
- AsyncPrefixWhileSequence
- AsyncStream
- AsyncThrowingCompactMapSequence
- AsyncThrowingDropWhileSequence
- AsyncThrowingFilterSequence
- AsyncThrowingFlatMapSequence
- AsyncThrowingMapSequence
- AsyncThrowingPrefixWhileSequence
- AsyncThrowingStream
- Observations
- TaskGroup
- ThrowingTaskGroup
Creating an Iterator
- makeAsyncIterator()) Creates the asynchronous iterator that produces elements of this asynchronous sequence.
- AsyncIterator The type of asynchronous iterator that produces elements of this asynchronous sequence.
- AsyncIteratorProtocol A type that asynchronously supplies the values of a sequence one at a time.
- Element The type of element produced by this asynchronous sequence.
Finding Elements
- contains(_:)) Returns a Boolean value that indicates whether the asynchronous sequence contains the given element.
- contains(where:)) Returns a Boolean value that indicates whether the asynchronous sequence contains an element that satisfies the given predicate.
- allSatisfy(_:)) Returns a Boolean value that indicates whether all elements produced by the asynchronous sequence satisfy the given predicate.
- first(where:)) Returns the first element of the sequence that satisfies the given predicate.
- min()) Returns the minimum element in an asynchronous sequence of comparable elements.
- min(by:)) Returns the minimum element in the asynchronous sequence, using the given predicate as the comparison between elements.
- max()) Returns the maximum element in an asynchronous sequence of comparable elements.
- max(by:)) Returns the maximum element in the asynchronous sequence, using the given predicate as the comparison between elements.
Selecting Elements
- prefix(_:)) Returns an asynchronous sequence, up to the specified maximum length, containing the initial elements of the base asynchronous sequence.
- AsyncPrefixSequence An asynchronous sequence, up to a specified maximum length, containing the initial elements of a base asynchronous sequence.
- prefix(while:)-2xy95) Returns an asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy the given predicate.
- AsyncPrefixWhileSequence An asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy a given predicate.
- prefix(while:)-6yp5n) Returns an asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy the given error-throwing predicate.
- AsyncThrowingPrefixWhileSequence An asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy the given error-throwing predicate.
Excluding Elements
- dropFirst(_:)) Omits a specified number of elements from the base asynchronous sequence, then passes through all remaining elements.
- AsyncDropFirstSequence An asynchronous sequence which omits a specified number of elements from the base asynchronous sequence, then passes through all remaining elements.
- drop(while:)-9sp3b) Omits elements from the base asynchronous sequence until a given closure returns false, after which it passes through all remaining elements.
- AsyncDropWhileSequence An asynchronous sequence which omits elements from the base sequence until a given closure returns false, after which it passes through all remaining elements.
- drop(while:)-67kgo) Omits elements from the base sequence until a given error-throwing closure returns false, after which it passes through all remaining elements.
- AsyncThrowingDropWhileSequence An asynchronous sequence which omits elements from the base sequence until a given error-throwing closure returns false, after which it passes through all remaining elements.
- filter(_:)-435af) Creates an asynchronous sequence that contains, in order, the elements of the base sequence that satisfy the given predicate.
- AsyncFilterSequence An asynchronous sequence that contains, in order, the elements of the base sequence that satisfy a given predicate.
- filter(_:)-2cc0l) Creates an asynchronous sequence that contains, in order, the elements of the base sequence that satisfy the given error-throwing predicate.
- AsyncThrowingFilterSequence An asynchronous sequence that contains, in order, the elements of the base sequence that satisfy the given error-throwing predicate.
Transforming a Sequence
- map(_:)-1q1k3) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements.
- AsyncMapSequence An asynchronous sequence that maps the given closure over the asynchronous sequence’s elements.
- map(_:)-70wgb) Creates an asynchronous sequence that maps the given error-throwing closure over the asynchronous sequence’s elements.
- AsyncThrowingMapSequence An asynchronous sequence that maps the given error-throwing closure over the asynchronous sequence’s elements.
- compactMap(_:)-gfdq) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements, omitting results that don’t return a value.
- AsyncCompactMapSequence An asynchronous sequence that maps a given closure over the asynchronous sequence’s elements, omitting results that don’t return a value.
- compactMap(_:)-1f8zn) Creates an asynchronous sequence that maps an error-throwing closure over the base sequence’s elements, omitting results that don’t return a value.
- AsyncThrowingCompactMapSequence An asynchronous sequence that maps an error-throwing closure over the base sequence’s elements, omitting results that don’t return a value.
- AsyncFlatMapSequence An asynchronous sequence that concatenates the results of calling a given transformation with each element of this sequence.
- AsyncThrowingFlatMapSequence An asynchronous sequence that concatenates the results of calling a given error-throwing transformation with each element of this sequence.
- reduce(_:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure.
- reduce(into:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure, given a mutable initial value.
Adapting Textual Sequences
- characters A non-blocking sequence of
Characterscreated by decoding the elements ofselfas UTF8. - AsyncCharacterSequence An asynchronous sequence of characters.
- unicodeScalars A non-blocking sequence of
UnicodeScalarscreated by decoding the elements ofselfas UTF8. - AsyncUnicodeScalarSequence An asychronous sequence of Unicode scalar values.
- lines A non-blocking sequence of newline-separated
Stringscreated by decoding the elements ofselfas UTF8. - AsyncLineSequence An asynchronous sequence of lines of text.
Associated Types
- Failure The type of errors produced when iteration over the sequence fails.
Instance Methods
- flatMap(_:)-4bl9a) Creates an asynchronous sequence that concatenates the results of calling the given transformation with each element of this sequence.
- flatMap(_:)-54rrt) Creates an asynchronous sequence that concatenates the results of calling the given transformation with each element of this sequence.
- flatMap(_:)-5j8ra) Creates an asynchronous sequence that concatenates the results of calling the given error-throwing transformation with each element of this sequence.
- flatMap(_:)-5rn1j) Creates an asynchronous sequence that concatenates the results of calling the given transformation with each element of this sequence.
Asynchronous Sequences
- AsyncStream An asynchronous sequence generated from a closure that calls a continuation to produce new elements.
- AsyncThrowingStream An asynchronous sequence generated from an error-throwing closure that calls a continuation to produce new elements.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
Structure
AsyncStream
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
An asynchronous sequence generated from a closure that calls a continuation to produce new elements.
struct AsyncStream<Element>Overview
AsyncStream conforms to AsyncSequence, providing a convenient way to create an asynchronous sequence without manually implementing an asynchronous iterator. In particular, an asynchronous stream is well-suited to adapt callback- or delegation-based APIs to participate with async-await.
You initialize an AsyncStream with a closure that receives an AsyncStream.Continuation. Produce elements in this closure, then provide them to the stream by calling the continuation’s yield(_:) method. When there are no further elements to produce, call the continuation’s finish() method. This causes the sequence iterator to produce a nil, which terminates the sequence. The continuation conforms to Sendable, which permits calling it from concurrent contexts external to the iteration of the AsyncStream.
An arbitrary source of elements can produce elements faster than they are consumed by a caller iterating over them. Because of this, AsyncStream defines a buffering behavior, allowing the stream to buffer a specific number of oldest or newest elements. By default, the buffer limit is Int.max, which means the value is unbounded.
Adapting Existing Code to Use Streams
To adapt existing callback code to use async-await, use the callbacks to provide values to the stream, by using the continuation’s yield(_:) method.
Consider a hypothetical QuakeMonitor type that provides callers with Quake instances every time it detects an earthquake. To receive callbacks, callers set a custom closure as the value of the monitor’s quakeHandler property, which the monitor calls back as necessary.
class QuakeMonitor {
var quakeHandler: ((Quake) -> Void)?
func startMonitoring() {…}
func stopMonitoring() {…}
}To adapt this to use async-await, extend the QuakeMonitor to add a quakes property, of type AsyncStream<Quake>. In the getter for this property, return an AsyncStream, whose build closure – called at runtime to create the stream – uses the continuation to perform the following steps:
1. Creates a QuakeMonitor instance. 2. Sets the monitor’s quakeHandler property to a closure that receives each Quake instance and forwards it to the stream by calling the continuation’s yield(_:) method. 3. Sets the continuation’s onTermination property to a closure that calls stopMonitoring() on the monitor. 4. Calls startMonitoring on the QuakeMonitor.
extension QuakeMonitor {
static var quakes: AsyncStream<Quake> {
AsyncStream { continuation in
let monitor = QuakeMonitor()
monitor.quakeHandler = { quake in
continuation.yield(quake)
}
continuation.onTermination = { @Sendable _ in
monitor.stopMonitoring()
}
monitor.startMonitoring()
}
}
}Because the stream is an AsyncSequence, the call point can use the for-await-in syntax to process each Quake instance as the stream produces it:
for await quake in QuakeMonitor.quakes {
print("Quake: \(quake.date)")
}
print("Stream finished.")Conforms To
Creating a Continuation-Based Stream
- init(_:bufferingPolicy:_:)) Constructs an asynchronous stream for an element type, using the specified buffering policy and element-producing closure.
- AsyncStream.Continuation.BufferingPolicy A strategy that handles exhaustion of a buffer’s capacity.
- AsyncStream.Continuation A mechanism to interface between synchronous code and an asynchronous stream.
Creating a Stream from an Asynchronous Function
- init(unfolding:onCancel:)) Constructs an asynchronous stream from a given element-producing closure, with an optional closure to handle cancellation.
Finding Elements
- contains(_:)) Returns a Boolean value that indicates whether the asynchronous sequence contains the given element.
- contains(where:)) Returns a Boolean value that indicates whether the asynchronous sequence contains an element that satisfies the given predicate.
- allSatisfy(_:)) Returns a Boolean value that indicates whether all elements produced by the asynchronous sequence satisfy the given predicate.
- first(where:)) Returns the first element of the sequence that satisfies the given predicate.
- min()) Returns the minimum element in an asynchronous sequence of comparable elements.
- min(by:)) Returns the minimum element in the asynchronous sequence, using the given predicate as the comparison between elements.
- max()) Returns the maximum element in an asynchronous sequence of comparable elements.
- max(by:)) Returns the maximum element in the asynchronous sequence, using the given predicate as the comparison between elements.
Selecting Elements
- prefix(_:)) Returns an asynchronous sequence, up to the specified maximum length, containing the initial elements of the base asynchronous sequence.
- prefix(while:)) Returns an asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy the given predicate.
Excluding Elements
- dropFirst(_:)) Omits a specified number of elements from the base asynchronous sequence, then passes through all remaining elements.
- drop(while:)) Omits elements from the base asynchronous sequence until a given closure returns false, after which it passes through all remaining elements.
- filter(_:)) Creates an asynchronous sequence that contains, in order, the elements of the base sequence that satisfy the given predicate.
Transforming a Sequence
- map(_:)-58nsf) Creates an asynchronous sequence that maps the given error-throwing closure over the asynchronous sequence’s elements.
- map(_:)-4a4la) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements.
- compactMap(_:)-7mgjd) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements, omitting results that don’t return a value.
- compactMap(_:)-944op) Creates an asynchronous sequence that maps an error-throwing closure over the base sequence’s elements, omitting results that don’t return a value.
- flatMap(_:)-vhhr) Creates an asynchronous sequence that concatenates the results of calling the given error-throwing transformation with each element of this sequence.
- reduce(_:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure.
- reduce(into:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure, given a mutable initial value.
Creating an Iterator
- makeAsyncIterator()) Creates the asynchronous iterator that produces elements of this asynchronous sequence.
- AsyncStream.Iterator The asynchronous iterator for iterating an asynchronous stream.
Supporting Types
- AsyncStream.AsyncIterator The type of asynchronous iterator that produces elements of this asynchronous sequence.
Type Methods
- makeStream(of:bufferingPolicy:)) Initializes a new AsyncStream and an AsyncStream.Continuation.
Default Implementations
Asynchronous Sequences
- AsyncSequence A type that provides asynchronous, sequential, iterated access to its elements.
- AsyncThrowingStream An asynchronous sequence generated from an error-throwing closure that calls a continuation to produce new elements.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
Structure
CheckedContinuation
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
A mechanism to interface between synchronous and asynchronous code, logging correctness violations.
struct CheckedContinuation<T, E> where E : ErrorOverview
A continuation is an opaque representation of program state. To create a continuation in asynchronous code, call the withCheckedContinuation(isolation:function:_:) or withCheckedThrowingContinuation(isolation:function:_:) function. To resume the asynchronous task, call the resume(returning:), resume(throwing:), resume(with:), or resume() method.
Important: You must call a resume method exactly once on every execution path throughout the program.
Resuming from a continuation more than once is undefined behavior. Never resuming leaves the task in a suspended state indefinitely, and leaks any associated resources. CheckedContinuation logs a message if either of these invariants is violated.
CheckedContinuation performs runtime checks for missing or multiple resume operations. UnsafeContinuation avoids enforcing these invariants at runtime because it aims to be a low-overhead mechanism for interfacing Swift tasks with event loops, delegate methods, callbacks, and other non-async scheduling mechanisms. However, during development, the ability to verify that the invariants are being upheld in testing is important. Because both types have the same interface, you can replace one with the other in most circumstances, without making other changes.
Conforms To
Initializers
- init(continuation:function:)) Creates a checked continuation from an unsafe continuation.
Instance Methods
- resume()) Resume the task awaiting the continuation by having it return normally from its suspension point.
- resume(returning:)) Resume the task awaiting the continuation by having it return normally from its suspension point.
- resume(throwing:)) Resume the task awaiting the continuation by having it throw an error from its suspension point.
- resume(with:)-3gh60) Resume the task awaiting the continuation by having it either return normally or throw an error based on the state of the given
Resultvalue. - resume(with:)-5n1a5) Resume the task awaiting the continuation by having it either return normally or throw an error based on the state of the given
Resultvalue.
Continuations
- withCheckedContinuation(isolation:function:_:)) Invokes the passed in closure with a checked continuation for the current task.
- withCheckedThrowingContinuation(isolation:function:_:)) Invokes the passed in closure with a checked continuation for the current task.
- UnsafeContinuation A mechanism to interface between synchronous and asynchronous code, without correctness checking.
- withUnsafeContinuation(isolation:_:)) Invokes the passed in closure with a unsafe continuation for the current task.
- UnsafeThrowingContinuation
- withUnsafeThrowingContinuation(isolation:_:)) Invokes the passed in closure with a unsafe continuation for the current task.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
API Collection
Concurrency
Perform asynchronous and parallel operations.
Essentials
- Code-along: Elevating an app with Swift concurrency Code along with the WWDC presenter to elevate a SwiftUI app with Swift concurrency.
- Updating an app to use strict concurrency Use this code to follow along with a guide to migrating your code to take advantage of the full concurrency protection that the Swift 6 language mode provides.
- Updating an App to Use Swift Concurrency Improve your app’s performance by refactoring your code to take advantage of asynchronous functions in Swift.
Tasks
- Task A unit of asynchronous work.
- TaskGroup A group that contains dynamically created child tasks.
- withTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingTaskGroup A group that contains throwing, dynamically created child tasks.
- withThrowingTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of throwing child tasks.
- TaskPriority The priority of a task.
- DiscardingTaskGroup A discarding group that contains dynamically created child tasks.
- withDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingDiscardingTaskGroup A throwing discarding group that contains dynamically created child tasks.
- withThrowingDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- UnsafeCurrentTask An unsafe reference to the current task.
Asynchronous Sequences
- AsyncSequence A type that provides asynchronous, sequential, iterated access to its elements.
- AsyncStream An asynchronous sequence generated from a closure that calls a continuation to produce new elements.
- AsyncThrowingStream An asynchronous sequence generated from an error-throwing closure that calls a continuation to produce new elements.
Continuations
- CheckedContinuation A mechanism to interface between synchronous and asynchronous code, logging correctness violations.
- withCheckedContinuation(isolation:function:_:)) Invokes the passed in closure with a checked continuation for the current task.
- withCheckedThrowingContinuation(isolation:function:_:)) Invokes the passed in closure with a checked continuation for the current task.
- UnsafeContinuation A mechanism to interface between synchronous and asynchronous code, without correctness checking.
- withUnsafeContinuation(isolation:_:)) Invokes the passed in closure with a unsafe continuation for the current task.
- UnsafeThrowingContinuation
- withUnsafeThrowingContinuation(isolation:_:)) Invokes the passed in closure with a unsafe continuation for the current task.
Actors
- Sendable A thread-safe type whose values can be shared across arbitrary concurrent contexts without introducing a risk of data races.
- Actor Common protocol to which all actors conform.
- AnyActor Common marker protocol providing a shared “base” for both (local)
Actorand (potentially remote)DistributedActortypes. - MainActor A singleton actor whose executor is equivalent to the main dispatch queue.
- GlobalActor A type that represents a globally-unique actor that can be used to isolate various declarations anywhere in the program.
- SendableMetatype A type whose metatype can be shared across arbitrary concurrent contexts without introducing a risk of data races.
- ConcurrentValue
- UnsafeSendable A type whose values can safely be passed across concurrency domains by copying, but which disables some safety checking at the conformance site.
- UnsafeConcurrentValue
- isolation()) Produce a reference to the actor to which the enclosing code is isolated, or
nilif the code is nonisolated. - extractIsolation(_:))
Task-Local Storage
- TaskLocal Wrapper type that defines a task-local value key.
- TaskLocal()) Macro that introduces a TaskLocal binding.
Executors
- Executor A service that can execute jobs.
- ExecutorJob A unit of schedulable work.
- SerialExecutor A service that executes jobs.
- TaskExecutor An executor that may be used as preferred executor by a task.
- PartialAsyncTask
- UnownedJob A unit of schedulable work.
- JobPriority The priority of this job.
- UnownedSerialExecutor An unowned reference to a serial executor (a
SerialExecutorvalue). - UnownedTaskExecutor
- globalConcurrentExecutor The global concurrent executor that is used by default for Swift Concurrency tasks.
- withTaskExecutorPreference(_:isolation:operation:)) Configure the current task hierarchy’s task executor preference to the passed TaskExecutor, and execute the passed in closure by immediately hopping to that executor.
Deprecated
- Job Deprecated equivalent of ExecutorJob.
Programming Tasks
- Input and Output Print values to the console, read from and write to text streams, and use command line arguments.
- Debugging and Reflection Fortify your code with runtime checks, and examine your values’ runtime representation.
- Macros Generate boilerplate code and perform other compile-time operations.
- Key-Path Expressions Use key-path expressions to access properties dynamically.
- Manual Memory Management Allocate and manage memory manually.
- Type Casting and Existential Types Perform casts between types or represent values of any type.
- C Interoperability Use imported C types or call C variadic functions.
- Operator Declarations Work with prefix, postfix, and infix operators.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
Structure
Task
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
A unit of asynchronous work.
@frozen struct Task<Success, Failure> where Success : Sendable, Failure : ErrorOverview
When you create an instance of Task, you provide a closure that contains the work for that task to perform. Tasks can start running immediately after creation; you don’t explicitly start or schedule them. After creating a task, you use the instance to interact with it — for example, to wait for it to complete or to cancel it. It’s not a programming error to discard a reference to a task without waiting for that task to finish or canceling it. A task runs regardless of whether you keep a reference to it. However, if you discard the reference to a task, you give up the ability to wait for that task’s result or cancel the task.
To support operations on the current task, which can be either a detached task or child task, Task also exposes class methods like yield(). Because these methods are asynchronous, they’re always invoked as part of an existing task.
Only code that’s running as part of the task can interact with that task. To interact with the current task, you call one of the static methods on Task.
A task’s execution can be seen as a series of periods where the task ran. Each such period ends at a suspension point or the completion of the task. These periods of execution are represented by instances of PartialAsyncTask. Unless you’re implementing a custom executor, you don’t directly interact with partial tasks.
For information about the language-level concurrency model that Task is part of, see Concurrency in The Swift Programming Language.
Task Cancellation
Tasks include a shared mechanism for indicating cancellation, but not a shared implementation for how to handle cancellation. Depending on the work you’re doing in the task, the correct way to stop that work varies. Likewise, it’s the responsibility of the code running as part of the task to check for cancellation whenever stopping is appropriate. In a long-task that includes multiple pieces, you might need to check for cancellation at several points, and handle cancellation differently at each point. If you only need to throw an error to stop the work, call the Task.checkCancellation() function to check for cancellation. Other responses to cancellation include returning the work completed so far, returning an empty result, or returning nil.
Cancellation is a purely Boolean state; there’s no way to include additional information like the reason for cancellation. This reflects the fact that a task can be canceled for many reasons, and additional reasons can accrue during the cancellation process.
Task closure lifetime
Tasks are initialized by passing a closure containing the code that will be executed by a given task.
After this code has run to completion, the task has completed, resulting in either a failure or result value, this closure is eagerly released.
Retaining a task object doesn’t indefinitely retain the closure, because any references that a task holds are released after the task completes. Consequently, tasks rarely need to capture weak references to values.
For example, in the following snippet of code it is not necessary to capture the actor as weak, because as the task completes it’ll let go of the actor reference, breaking the reference cycle between the Task and the actor holding it.
struct Work: Sendable {}
actor Worker {
var work: Task<Void, Never>?
var result: Work?
deinit {
// even though the task is still retained,
// once it completes it no longer causes a reference cycle with the actor
print("deinit actor")
}
func start() {
work = Task {
print("start task work")
try? await Task.sleep(for: .seconds(3))
self.result = Work() // we captured self
print("completed task work")
// but as the task completes, this reference is released
}
// we keep a strong reference to the task
}
}And using it like this:
await Worker().start()Note that the actor is only retained by the start() method’s use of self, and that the start method immediately returns, without waiting for the unstructured Task to finish. Once the task is completed and its closure is destroyed, the strong reference to the actor is also released allowing the actor to deinitialize as expected.
Therefore, the above call will consistently result in the following output:
start task work
completed task work
deinit actorConforms To
Creating a Task
- init(name:priority:operation:)-2dll5) Runs the given nonthrowing operation asynchronously as part of a new unstructured top-level task.
- init(name:priority:operation:)-43wmk) Runs the given throwing operation asynchronously as part of a new unstructured top-level task.
- init(name:executorPreference:priority:operation:)-59bfi) Runs the given throwing operation asynchronously as part of a new unstructured top-level task.
- init(name:executorPreference:priority:operation:)-81pay) Runs the given nonthrowing operation asynchronously as part of a new unstructured top-level task.
- currentPriority The current task’s priority.
- basePriority The current task’s base priority.
- withTaskPriorityEscalationHandler(operation:onPriorityEscalated:)) Runs the passed
operationwhile registering a task priority escalation handler. The handler will be triggered concurrently to the current task if the current is subject to priority escalation.
Creating a Detached Task
- detached(name:priority:operation:)-795w1) Runs the given throwing operation asynchronously as part of a new unstructured detached top-level task.
- detached(name:priority:operation:)-9xki7) Runs the given nonthrowing operation asynchronously as part of a new unstructured detached top-level task.
- detached(name:executorPreference:priority:operation:)-6r16s) Runs the given throwing operation asynchronously as part of a new unstructured detached top-level task.
- detached(name:executorPreference:priority:operation:)-75ffe) Runs the given nonthrowing operation asynchronously as part of a new unstructured detached top-level task.
Creating a Task that Starts Immediately
- immediate(name:priority:executorPreference:operation:)-88o80) Create and immediately start running a new detached task in the context of the calling thread/task.
- immediate(name:priority:executorPreference:operation:)-9bghc) Create and immediately start running a new detached task in the context of the calling thread/task.
- immediateDetached(name:priority:executorPreference:operation:)-52ipd) Create and immediately start running a new task in the context of the calling thread/task.
- immediateDetached(name:priority:executorPreference:operation:)-7h41b) Create and immediately start running a new task in the context of the calling thread/task.
Accessing Results
- value The result from a throwing task, after it completes.
- value The result from a nonthrowing task, after it completes.
- result The result or error from a throwing task, after it completes.
Accessing the Current Task’s Name
- name Returns the human-readable name of the current task, if it was set during the tasks’ creation.
Canceling Tasks
- CancellationError An error that indicates a task was canceled.
- cancel()) Cancels this task.
- isCancelled A Boolean value that indicates whether the task should stop executing.
- isCancelled A Boolean value that indicates whether the task should stop executing.
- checkCancellation()) Throws an error if the task was canceled.
- withTaskCancellationHandler(handler:operation:))
- withTaskCancellationHandler(operation:onCancel:isolation:)) Execute an operation with a cancellation handler that’s immediately invoked if the current task is canceled.
Suspending Execution
- yield()) Suspends the current task and allows other tasks to execute.
- sleep(nanoseconds:)) Suspends the current task for at least the given duration in nanoseconds.
- sleep(for:tolerance:clock:)) Suspends the current task for the given duration.
- sleep(until:tolerance:clock:)) Suspends the current task until the given deadline within a tolerance.
Escalating Tasks
- escalatePriority(to:)) Manually escalate the task
priorityof this task to thenewPriority.
Comparing Tasks
- ==(_:_:)) Returns a Boolean value indicating whether two values are equal.
- !=(_:_:)) Returns a Boolean value indicating whether two values are not equal.
- hashValue The hash value.
- hash(into:)) Hashes the essential components of this value by feeding them into the given hasher.
Deprecated
- Task.Group
- Task.Handle
- Task.Priority
- CancellationError())
- getResult())
- get()-4i2gt)
- get()-4ohks)
- sleep(_:))
- suspend())
- runDetached(priority:operation:)-88zf5) Deprecated, available only for source compatibility reasons.
- runDetached(priority:operation:)-8s8lh) Deprecated, available only for source compatibility reasons.
- withCancellationHandler(handler:operation:))
- withGroup(resultType:returning:body:))
Default Implementations
Tasks
- TaskGroup A group that contains dynamically created child tasks.
- withTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingTaskGroup A group that contains throwing, dynamically created child tasks.
- withThrowingTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of throwing child tasks.
- TaskPriority The priority of a task.
- DiscardingTaskGroup A discarding group that contains dynamically created child tasks.
- withDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingDiscardingTaskGroup A throwing discarding group that contains dynamically created child tasks.
- withThrowingDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- UnsafeCurrentTask An unsafe reference to the current task.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Navigation: Swift
Structure
TaskGroup
Available on: iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.0+, macOS 10.15+, tvOS 13.0+, visionOS 1.0+, watchOS 6.0+
A group that contains dynamically created child tasks.
@frozen struct TaskGroup<ChildTaskResult> where ChildTaskResult : SendableOverview
To create a task group, call the withTaskGroup(of:returning:body:) method.
Don’t use a task group from outside the task where you created it. In most cases, the Swift type system prevents a task group from escaping like that because adding a child task to a task group is a mutating operation, and mutation operations can’t be performed from a concurrent execution context like a child task.
Structured Concurrency
Structured concurrency is a way to organize your program, and tasks, in such a way that tasks don’t outlive the scope in which they are created. Within a structured task hierarchy, no child task remains running longer than its parent task. This guarantee simplifies reasoning about resource usage, and is a powerful mechanism that you can use to write well-behaved concurrent programs.
A task group is the primary way to create structured concurrency tasks in Swift. Another way of creating structured tasks is an async let declaration.
Structured concurrency tasks are often called “child tasks” because of their relationship with their parent task. A child task inherits the parent’s priority, task-local values, and is structured in the sense that its lifetime never exceeds the lifetime of the parent task.
A task group always waits for all child tasks to complete before it’s destroyed. Specifically, with...TaskGroup APIs don’t return until all the child tasks created in the group’s scope have completed running.
Structured concurrency APIs (including task groups and async let), always waits for the completion of tasks contained within their scope before returning. Specifically, this means that even if you await a single task result and return it from a withTaskGroup function body, the group automatically waits for all the remaining tasks before returning:
func takeFirst(actions: [@Sendable () -> Int]) async -> Int? {
await withTaskGroup { group in
for action in actions {
group.addTask { action() }
}
return await group.next() // return the first action to complete
} // the group will ALWAYS await the completion of all the actions (!)
}In the above example, even though the code returns the first collected integer from all actions added to the task group, the task group always, automatically, waits for the completion of all the resulting tasks.
You can use group.cancelAll() to signal cancellation to the remaining in-progress tasks, however this doesn’t interrupt their execution automatically. Rather, the child tasks need to cooperatively react to the cancellation, and return early if that’s possible.
To create unstructured concurrency tasks, you can use Task.init, Task.detached or Task.immediate.
Task Group Cancellation
You can cancel a task group and all of its child tasks by calling the cancelAll() method on the task group, or by canceling the task in which the group is running.
If you call addTask(name:priority:operation:) to create a new task in a canceled group, that task is immediately canceled after creation. Alternatively, you can call addTaskUnlessCancelled(name:priority:operation:), which doesn’t create the task if the group has already been canceled. Choosing between these two functions lets you control how to react to cancellation within a group: some child tasks need to run regardless of cancellation, but other tasks are better not even being created when you know they can’t produce useful results.
In nonthrowing task groups the tasks you add to a group with this method are nonthrowing, those tasks can’t respond to cancellation by throwing CancellationError. The tasks must handle cancellation in some other way, such as returning the work completed so far, returning an empty result, or returning nil. For tasks that need to handle cancellation by throwing an error, use the withThrowingTaskGroup(of:returning:body:) method instead.
Task execution order
Tasks added to a task group execute concurrently, and may be scheduled in any order.
Cancellation behavior
A task group becomes canceled in one of the following ways:
- When cancelAll()) is invoked on it.
- When the Task running this task group is canceled.
Because a TaskGroup is a structured concurrency primitive, cancellation is automatically propagated through all of its child-tasks (and their child tasks).
A canceled task group can still keep adding tasks, however they will start being immediately canceled, and might respond accordingly. To avoid adding new tasks to an already canceled task group, use addTaskUnlessCancelled(name:priority:body:) rather than the plain addTask(name:priority:body:) which adds tasks unconditionally.
For information about the language-level concurrency model that TaskGroup is part of, see Concurrency in The Swift Programming Language.
See Also: ThrowingTaskGroup
See Also: DiscardingTaskGroup
See Also: ThrowingDiscardingTaskGroup
Conforms To
Adding Tasks to a Task Group
- addTask(priority:operation:)) Adds a child task to the group.
- addTask(name:priority:operation:)) Adds a child task to the group.
- addTask(executorPreference:priority:operation:)) Adds a child task to the group.
- addTask(name:executorPreference:priority:operation:)) Adds a child task to the group.
- addTaskUnlessCancelled(name:executorPreference:priority:operation:)) Adds a child task to the group, unless the group has been canceled. Returns a boolean value indicating if the task was successfully added to the group or not.
- addTaskUnlessCancelled(executorPreference:priority:operation:)) Adds a child task to the group, unless the group has been canceled. Returns a boolean value indicating if the task was successfully added to the group or not.
- addTaskUnlessCancelled(name:priority:operation:)) Adds a child task to the group, unless the group has been canceled. Returns a boolean value indicating if the task was successfully added to the group or not.
- addTaskUnlessCancelled(priority:operation:)) Adds a child task to the group, unless the group has been canceled. Returns a boolean value indicating if the task was successfully added to the group or not.
- addImmediateTask(name:priority:executorPreference:operation:)) Add a child task to the group and immediately start running it in the context of the calling thread/task.
- addImmediateTaskUnlessCancelled(name:priority:executorPreference:operation:)) Add a child task to the group and immediately start running it in the context of the calling thread/task.
Accessing Individual Results
- next())
- next(isolation:)) Waits for the next child task to complete, and returns the value it returned.
- isEmpty A Boolean value that indicates whether the group has any remaining tasks.
- waitForAll(isolation:)) Wait for all of the group’s remaining tasks to complete.
Accessing an Asynchronous Sequence of Results
- makeAsyncIterator()) Creates the asynchronous iterator that produces elements of this asynchronous sequence.
- allSatisfy(_:)) Returns a Boolean value that indicates whether all elements produced by the asynchronous sequence satisfy the given predicate.
- compactMap(_:)-944od) Creates an asynchronous sequence that maps an error-throwing closure over the base sequence’s elements, omitting results that don’t return a value.
- compactMap(_:)-7mgj1) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements, omitting results that don’t return a value.
- contains(_:)) Returns a Boolean value that indicates whether the asynchronous sequence contains the given element.
- contains(where:)) Returns a Boolean value that indicates whether the asynchronous sequence contains an element that satisfies the given predicate.
- drop(while:)) Omits elements from the base asynchronous sequence until a given closure returns false, after which it passes through all remaining elements.
- dropFirst(_:)) Omits a specified number of elements from the base asynchronous sequence, then passes through all remaining elements.
- filter(_:)) Creates an asynchronous sequence that contains, in order, the elements of the base sequence that satisfy the given predicate.
- first(where:)) Returns the first element of the sequence that satisfies the given predicate.
- flatMap(_:)-vhi3) Creates an asynchronous sequence that concatenates the results of calling the given error-throwing transformation with each element of this sequence.
- map(_:)-58nsr) Creates an asynchronous sequence that maps the given error-throwing closure over the asynchronous sequence’s elements.
- map(_:)-4a4kq) Creates an asynchronous sequence that maps the given closure over the asynchronous sequence’s elements.
- max()) Returns the maximum element in an asynchronous sequence of comparable elements.
- max(by:)) Returns the maximum element in the asynchronous sequence, using the given predicate as the comparison between elements.
- min()) Returns the minimum element in an asynchronous sequence of comparable elements.
- min(by:)) Returns the minimum element in the asynchronous sequence, using the given predicate as the comparison between elements.
- prefix(_:)) Returns an asynchronous sequence, up to the specified maximum length, containing the initial elements of the base asynchronous sequence.
- prefix(while:)) Returns an asynchronous sequence, containing the initial, consecutive elements of the base sequence that satisfy the given predicate.
- reduce(_:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure.
- reduce(into:_:)) Returns the result of combining the elements of the asynchronous sequence using the given closure, given a mutable initial value.
Canceling Tasks
- isCancelled A Boolean value that indicates whether the group was canceled.
- cancelAll()) Cancel all of the remaining tasks in the group.
Supporting Types
- TaskGroup.Element The type of element produced by this asynchronous sequence.
- TaskGroup.Iterator A type that provides an iteration interface over the results of tasks added to the group.
- TaskGroup.AsyncIterator The type of asynchronous iterator that produces elements of this asynchronous sequence.
Deprecated
- add(priority:operation:))
- async(priority:operation:))
- asyncUnlessCancelled(priority:operation:))
- spawn(priority:operation:))
- spawnUnlessCancelled(priority:operation:))
Default Implementations
Tasks
- Task A unit of asynchronous work.
- withTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingTaskGroup A group that contains throwing, dynamically created child tasks.
- withThrowingTaskGroup(of:returning:isolation:body:)) Starts a new scope that can contain a dynamic number of throwing child tasks.
- TaskPriority The priority of a task.
- DiscardingTaskGroup A discarding group that contains dynamically created child tasks.
- withDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- ThrowingDiscardingTaskGroup A throwing discarding group that contains dynamically created child tasks.
- withThrowingDiscardingTaskGroup(returning:isolation:body:)) Starts a new scope that can contain a dynamic number of child tasks.
- UnsafeCurrentTask An unsafe reference to the current task.
---
Extracted from Apple DocC JSON by apple-skills tooling. This is unofficial content. All documentation belongs to Apple Inc.
Related skills
How it compares
Use swift-concurrency alongside swiftui when concurrency questions arise during UI work; swift-concurrency focuses on async/await and actors, not view layout or navigation.
FAQ
What topics does swift-concurrency cover?
swift-concurrency provides local reference files for Task, TaskGroup, Actor, AsyncSequence, AsyncStream, and CheckedContinuation plus a concurrency overview index. Agents grep these files before fetching additional Apple documentation from sosumi.ai mirrors.
How should agents fetch docs not in swift-concurrency?
swift-concurrency instructs agents to search its 7 local markdown files first, then grep sibling installed Apple skills, and only then fetch missing pages via sosumi.ai using paths from concurrency-overview.md.
Is swift-concurrency user-invocable?
swift-concurrency is user-invocable and runs in a forked Explore agent context, letting developers query Swift Concurrency APIs directly without loading unrelated Apple skill content into the main session.