【发布时间】:2020-11-19 10:14:26
【问题描述】:
我正在尝试创建一个组合管道,该管道使用 Unsplash API 获取五个随机照片 url,然后从每个 url 下载一张照片。我遇到的问题是图像大多相同。有时(我不知道为什么)其中一张图片会与其他四张不同。
任何帮助将不胜感激。除了 UnSplash Api 密钥之外,我还包含了所有必要的代码。
static func fetchRandomPhotos() -> AnyPublisher<UIImage, Error>{
let string = createURL(path: "/photos/random")
return [1,2,3,4,5]
.publisher
.flatMap{ i -> AnyPublisher<UnsplashImageResults, Error> in
return self.downloadAndDecode(string, type: UnsplashImageResults.self)
}
.flatMap{ result -> AnyPublisher<UIImage, Error> in
print(result.urls.thumb)
let url = URL(string: result.urls.thumb)!
return URLSession.shared.dataTaskPublisher(for: url)
.map { UIImage(data: $0.data)! }
.mapError{_ in NetworkError.invalidURL}
.eraseToAnyPublisher()
}
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
struct UnsplashURLs: Decodable{
let full: String
let regular: String
let small: String
let thumb: String
}
struct UnsplashImageResults: Decodable{
let urls: UnsplashURLs
}
enum NetworkError: LocalizedError{
case invalidURL
var errorDescription: String? {
switch self {
case .invalidURL:
return "The url is invalid"
}
}
}
static private func createURL(path: String)-> String{
var components = URLComponents()
components.scheme = "https"
components.host = "api.unsplash.com"
components.path = path
components.queryItems = [
URLQueryItem(name: "client_id", value: "YOUR API KEY HERE")
]
return components.string!
}
static private func downloadAndDecode<T:Decodable>(_ urlString: String, type: T.Type) -> AnyPublisher<T, Error>{
guard let url = URL(string: urlString) else{
return Fail(error: NetworkError.invalidURL).eraseToAnyPublisher()
}
return URLSession.shared.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: T.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
class UnsplashImagesViewModel: ObservableObject{
var subscriptions = Set<AnyCancellable>()
@Published var images = [UIImage]()
init(){
UnsplashAPI.fetchRandomPhotos()
.sink { (_) in
} receiveValue: { image in
self.images.append(image)
}.store(in: &subscriptions)
}
}
struct UnsplashImagesGrid: View {
@StateObject private var model = UnsplashImagesViewModel()
var body: some View {
List(model.images, id: \.self){ image in
Image(uiImage: image)
}
}
}
【问题讨论】: