问题描述
我有两个 URL 列表,它们返回一些图像链接。 列表被传递到像
这样的未来static func loadRecentEpisodeImagesFuture(request: [URL]) -> AnyPublisher<[RecentEpisodeImages],Never> {
return Future { promise in
print(request)
networkAPI.recentEpisodeImages(url: request)
.sink(receiveCompletion: { _ in },receiveValue: { recentEpisodeImages in
promise(.success(recentEpisodeImages))
})
.store(in: &recentimagesSubscription)
}
.erasetoAnyPublisher()
}
调用:
/// Get a list of image sizes associated with a featured episode .
func featuredEpisodeImages(featuredUrl: [URL]) -> AnyPublisher<[FeaturedEpisodeImages],Error> {
let featuredEpisodesImages = featuredUrl.map { (featuredUrl) -> AnyPublisher<FeaturedEpisodeImages,Error> in
return URLSession.shared
.dataTaskPublisher(for: featuredUrl)
.map(\.data)
.decode(type: FeaturedEpisodeImages.self,decoder: decoder)
.receive(on: networkApiQueue)
.catch { _ in Empty<FeaturedEpisodeImages,Error>() }
.print("###Featured###")
.erasetoAnyPublisher()
}
return Publishers.MergeMany(featuredEpisodesImages).collect().erasetoAnyPublisher()
}
/// Get a list of image sizes associated with a recent episode .
func recentEpisodeImages(recentUrl: [URL]) -> AnyPublisher<[RecentEpisodeImages],Error> {
let recentEpisodesImages = recentUrl.map { (recentUrl) -> AnyPublisher<RecentEpisodeImages,Error> in
return URLSession.shared
.dataTaskPublisher(for: recentUrl)
.map(\.data)
.decode(type: RecentEpisodeImages.self,decoder: decoder)
.receive(on: networkApiQueue)
.catch { _ in Empty<RecentEpisodeImages,Error>() }
.print("###Recent###")
.erasetoAnyPublisher()
}
return Publishers.MergeMany(recentEpisodesImages).collect().erasetoAnyPublisher()
}
并附加到应用状态:
/// Takes an action and returns a future mapped to another action.
static func recentEpisodeImages(action: RequestRecentEpisodeImages) -> AnyPublisher<Action,Never> {
return loadRecentEpisodeImagesFuture(request: action.request)
.receive(on: networkApiQueue)
.map({ images in ResponseRecentEpisodeImages(response: images) })
.replaceError(with: RequestFailed())
.erasetoAnyPublisher()
}
好像是:
return Publishers.MergeMany(recentEpisodes).collect().erasetoAnyPublisher()
不会给我一个可靠的下游值,因为最后完成的响应会覆盖较早的响应。
我能够记录这两个系列请求的响应。两者都在处理正确的数组并返回正确的 json。
我想要类似的东西:
return recentEpisodeImages
但目前这给了我错误
无法将类型为“[AnyPublisher
如何收集内部发布者的值并将其返回为
AnyPublisher<[RecentEpisodeImages],Error>
解决方法
您仍然没有回答我关于您要实现的目标是什么的问题。如果问题是如何将 URL 数组转换为从这些 URL 下载和处理数据时得到的数组,那么答案是:将数组转换为序列发布者,通过 {{1 }} 和 flatMap
结果。
例如,这里是如何将表示图像的 URL 数组转换为实际图像的数组(与您要执行的操作不同,但可能非常接近):
collect
以下是测试方法:
func publisherOfArrayOfImages(urls:[URL]) -> AnyPublisher<[UIImage],Error> {
urls.publisher
.flatMap { (url:URL) -> AnyPublisher<UIImage,Error> in
return URLSession.shared.dataTaskPublisher(for: url)
.compactMap { UIImage(data: $0.0) }
.mapError { $0 as Error }
.eraseToAnyPublisher()
}.collect().eraseToAnyPublisher()
}
您会看到管道底部弹出的是一个包含三个图像的数组,对应于我们开始使用的三个 URL 数组。
(请注意,结果数组的 order 是随机的。我们异步获取图像,因此结果以它们喜欢的任何顺序返回到我们的机器。有办法解决这个问题问题,但这不是你问的问题。)