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 fail37.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)