As far as I read the proposal SE-0298Async/Await: Sequences, implementing AsyncSequence is far from intuitive.
You may need to write something like this:
func fetchAsyncImage(request: URLRequest) -> AsyncPhotos {
return AsyncPhotos(request: request)
}
struct AsyncPhotos: AsyncSequence {
typealias Element = UIImage
let request: URLRequest
struct AsyncIterator: AsyncIteratorProtocol {
let request: URLRequest
var photosIterator: Array<Photo>.Iterator?
mutating func next() async throws -> UIImage? {
if photosIterator == nil {
let (data, response) = try await URLSession.shared.data(for: request)
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
throw FetchError.badRequest
}
let photos = try JSONDecoder().decode([Photo].self, from: data)
photosIterator = photos.makeIterator()
}
guard let photo = photosIterator?.next() else {
return nil
}
do {
guard let imageURL = URL(string: photo.urlPath) else {
throw FetchError.noURL
}
let (imageData, imageResponse) = try await URLSession.shared.data(from: imageURL)
guard (imageResponse as? HTTPURLResponse)?.statusCode == 200 else {
throw FetchError.invalidImageURL
}
guard let image = UIImage(data: imageData) else {
throw FetchError.badImage
}
return image
} catch {
throw FetchError.invalidImageURL
}
}
}
func makeAsyncIterator() -> AsyncIterator {
AsyncIterator(request: request)
}
}
(Not tested. You may need to fix many parts.)
I'm not sure if AsyncStream/AsyncThrowingStream can improve the way implementing AsyncSequence.
Topic:
Programming Languages
SubTopic:
Swift
Tags: