How do I wrap URLSession delegate methods in AsyncSequence in Swift?

In Swift, you can wrap `URLSession` delegate methods in an `AsyncSequence` to handle network requests in a more modern and asynchronous way. This allows you to work with the delegate methods using Swift's structured concurrency features.

Example of Wrapping `URLSession` Delegate Methods


// Define a sequence for URLSession delegate methods
struct URLSessionAsyncSequence: AsyncSequence {
    typealias Element = Data

    let urlSession: URLSession
    let url: URL

    func makeAsyncIterator() -> URLSessionAsyncIterator {
        return URLSessionAsyncIterator(urlSession: urlSession, url: url)
    }
}

struct URLSessionAsyncIterator: AsyncIteratorProtocol {
    let urlSession: URLSession
    let url: URL
    private var continuation: UnsafeContinuation? // Continuation for async sequence

    mutating func next() async -> Data? {
        // Create a task to perform the network request
        await withCheckedContinuation { continuation in
            self.continuation = continuation
            let task = urlSession.dataTask(with: url) { data, response, error in
                if let data = data {
                    continuation.resume(returning: data)
                } else {
                    continuation.resume(returning: nil)
                }
            }
            task.resume()
        }
    }
}

// Usage example
let url = URL(string: "https://api.example.com/data")!
let session = URLSession.shared
let asyncSequence = URLSessionAsyncSequence(urlSession: session, url: url)

Task {
    for await data in asyncSequence {
        print("Received data: \(data.count) bytes")
    }
}
    

Swift URLSession AsyncSequence concurrency async/await modern networking