0
0
Swiftprogramming~5 mins

Async sequences (AsyncSequence) in Swift

Choose your learning style9 modes available
Introduction

Async sequences let you work with values that come over time, like waiting for messages or data without stopping your program.

When you want to handle data that arrives slowly, like user input or network responses.
When you need to process events one by one as they happen, such as button taps or sensor updates.
When reading lines from a file or stream without blocking the app.
When you want to write clean code that waits for multiple values asynchronously.
When you want to combine or transform streams of data easily.
Syntax
Swift
struct MyAsyncSequence: AsyncSequence {
    typealias Element = Int

    struct AsyncIterator: AsyncIteratorProtocol {
        var current = 0

        mutating func next() async -> Int? {
            guard current < 5 else { return nil }
            defer { current += 1 }
            return current
        }
    }

    func makeAsyncIterator() -> AsyncIterator {
        AsyncIterator()
    }
}

An AsyncSequence must define an AsyncIterator that produces values asynchronously.

The next() method returns the next value or nil when done.

Examples
This loops over the async sequence and prints each number as it arrives.
Swift
for await number in MyAsyncSequence() {
    print(number)
}
This manually creates an iterator and fetches values one by one inside an async task.
Swift
let numbers = MyAsyncSequence()
var iterator = numbers.makeAsyncIterator()

Task {
    while let number = await iterator.next() {
        print(number)
    }
}
Sample Program

This program counts down from 3 to 1, waiting half a second between each number, then prints "Blast off!".

Swift
import Foundation

struct Countdown: AsyncSequence {
    typealias Element = Int

    struct AsyncIterator: AsyncIteratorProtocol {
        var count: Int

        mutating func next() async -> Int? {
            guard count > 0 else { return nil }
            try? await Task.sleep(nanoseconds: 500_000_000) // wait 0.5 seconds
            defer { count -= 1 }
            return count
        }
    }

    let start: Int

    func makeAsyncIterator() -> AsyncIterator {
        AsyncIterator(count: start)
    }
}

@main
struct Main {
    static func main() async {
        let countdown = Countdown(start: 3)
        for await number in countdown {
            print("Countdown: \(number)")
        }
        print("Blast off!")
    }
}
OutputSuccess
Important Notes

Use for await to loop over async sequences easily.

Async sequences help keep your app responsive by not blocking while waiting for data.

Remember to mark functions using async sequences with async and run them in async contexts.

Summary

Async sequences let you handle streams of values that come over time without blocking.

Define an AsyncIterator with a next() method that returns values asynchronously.

Use for await loops to process these values simply and clearly.