AsyncIteratorProtocol
A type that asynchronously supplies the values of a sequence one at a time.
- iOS
- 13.0+
- macOS
- 10.15+
- tvOS
- 13.0+
- watchOS
- 6.0+
protocol AsyncIteratorProtocol<Element, Failure>
Browse conforming typesThe AsyncIteratorProtocol
defines the type returned by the makeAsyncIterator()
method of the AsyncSequence
protocol. In short, the iterator is what produces the asynchronous sequence’s values. The protocol defines a single asynchronous method, next()
, which either produces the next element of the sequence, or returns nil
to signal the end of the sequence.
To implement your own AsyncSequence
, implement a wrapped type that conforms to AsyncIteratorProtocol
. The following example shows a Counter
type that uses an inner iterator to monotonically generate Int
values until reaching a howHigh
value. While this example isn’t itself asynchronous, it shows the shape of a custom sequence and iterator, and how to use it as if it were asynchronous:
struct Counter: AsyncSequence {
typealias Element = Int
let howHigh: Int
struct AsyncIterator: AsyncIteratorProtocol {
let howHigh: Int
var current = 1
mutating func next() async -> Int? {
// A genuinely asynchronous implementation uses the `Task`
// API to check for cancellation here and return early.
guard current <= howHigh else {
return nil
}
let result = current
current += 1
return result
}
}
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator(howHigh: howHigh)
}
}
At the call site, this looks like:
for await number in Counter(howHigh: 10) {
print(number, terminator: " ")
}
// Prints "1 2 3 4 5 6 7 8 9 10 "
End of Iteration
The iterator returns nil
to indicate the end of the sequence. After returning nil
(or throwing an error) from next()
, the iterator enters a terminal state, and all future calls to next()
must return nil
.
Cancellation
Types conforming to AsyncIteratorProtocol
should use the cancellation primitives provided by Swift’s Task
API. The iterator can choose how to handle and respond to cancellation, including:
Checking the
isCancelled
value of the currentTask
insidenext()
and returningnil
to terminate the sequence.Calling
checkCancellation()
on theTask
, which throws aCancellationError
.Implementing
next()
with awithTaskCancellationHandler(handler:operation:)
invocation to immediately react to cancellation.
If the iterator needs to clean up on cancellation, it can do so after checking for cancellation as described above, or in deinit
if it’s a reference type.