AsyncSequence, AsyncStream and Bridging Legacy Code

37.1 AsyncSequence

struct Countdown: AsyncSequence {
    typealias Element = Int
    let start: Int
    struct AsyncIterator: AsyncIteratorProtocol {
        var current: Int
        mutating func next() async -> Int? {
            guard current > 0 else { return nil }
            try? await Task.sleep(for: .seconds(1))
            defer { current -= 1 }
            return current
        }
    }
    func makeAsyncIterator() -> AsyncIterator { AsyncIterator(current: start) }
}

for await n in Countdown(start: 3) { print(n) }
let evens = Countdown(start: 10).filter { $0.isMultiple(of: 2) }.map { $0 * 10 }
for await v in evens { print(v) }

37.2 AsyncStream (Bridging Callbacks/Delegates)

func locationUpdates() -> AsyncStream<CLLocation> {
    AsyncStream { continuation in
        let delegate = LocationDelegate { location in
            continuation.yield(location)
        }
        continuation.onTermination = { _ in delegate.stop() }
        delegate.start()
    }
}

let (stream, continuation) = AsyncStream.makeStream(of: Int.self, bufferingPolicy: .bufferingNewest(10))
Task { for await value in stream { print(value) } }
continuation.yield(1); continuation.yield(2); continuation.finish()
// AsyncThrowingStream for streams that can fail

37.3 Continuations (Bridging Completion Handlers)

Many Apple APIs were automatically bridged: Objective-C completion-handler methods appear as async in Swift.

swift-async-algorithms package: merge, combineLatest, zip, debounce, throttle, chunked, AsyncChannel, timer.

func legacyFetch(completion: @escaping (Result<Data, Error>) -> Void) { /* ... */ }

func modernFetch() async throws -> Data {
    try await withCheckedThrowingContinuation { continuation in
        legacyFetch { result in
            continuation.resume(with: result)    // must resume EXACTLY once
        }
    }
}
// withCheckedContinuation (non-throwing), withUnsafeContinuation (no runtime checks)