Swift Combine - 访问单独的发布者列表

问题描述

我有两个 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”

如何收集内部发布者的值并将其返回为

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 是随机的。我们异步获取图像,因此结果以它们喜欢的任何顺序返回到我们的机器。有办法解决这个问题问题,但这不是你问的问题。)