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
isCancelledvalue of the currentTaskinsidenext()and returningnilto 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.