How to iterate over a custom object given below with async sequence
enum FetchError: Error {
case badImage
case badRequest
case invalidImageURL
case noURL
case failedToFetchImage
}
struct Photo: Codable {
let albumId: Int
let id: Int
let title: String
let urlPath: String
let thumbnailUrl: String
}
What i have tried :-
func fetchAsyncImage(request:URLRequest) async throws -> [UIImage] {
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)
guard let imagePath = photos.first?.urlPath,
let imageURL = URL.init(string: imagePath) else { throw FetchError.noURL }
var imageArr:[UIImage] = []
// getting error in following 2 lines
// Error: For-in loop requires '[Photo]' to conform to 'AsyncSequence'
for await photo in photos {
// Error: Type of expression is ambiguous without more context
guard let imagePath = photo.urlPath,
let imageURL = URL.init(string: imagePath) else { throw FetchError.noURL }
do {
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 }
imageArr.append(image)
} catch {
throw FetchError.failedToFetchImage
}
}
return imageArr
}
I tried implementing AsyncSequenc and AsyncIteratorProtocol on Photo struct as follows:-
struct Photo: Codable, AsyncSequence {
typealias Element = URL
let albumId: Int
let id: Int
let title: String
let urlPath: String
let thumbnailUrl: String
struct AsyncIterator: AsyncIteratorProtocol {
let urlPath: String
mutating func next() async throws -> URL? {
do {
guard let imageURL = URL.init(string: urlPath) else { throw FetchError.noURL }
return imageURL
} catch {
throw FetchError.invalidImageURL
}
}
}
func makeAsyncIterator() -> AsyncIterator {
AsyncIterator(urlPath: urlPath)
}
}