RxSwift:延迟可观察,直到另一个可观察量完成



我从服务器加载帖子,并且只想图像全部加载时才显示它们。这是我试图做的:

postsRepository
    .fetchPosts()
    .flatMap { posts -> Observable<[Post]> in
        return Observable.merge(posts.map({ /* Code that returns Observable<UIImage> */ }))
            .takeLast(1)
            .map { _ in posts }
    }

但是,上面的这段代码加载图像两次:一次获取所有帖子,一次我将帖子绑定到表视图。如何处理?

这是一个有趣的...

let postsWithImages = postsRepository
    .fetchPosts()
    .flatMap { posts in
        Observable.combineLatest(
            posts
                .map { $0.imageURL }
                .map { URLSession.shared.rx.data(request: URLRequest(url: $0))
                    .map { UIImage(data: $0) }
                    .catchErrorJustReturn(nil)
                }
            )
            .map { zip(posts, $0) }
    }
    .map { $0.map { (post: $0.0, image: $0.1) } }

如果您习惯于使用Zip2Sequence,那么最后map可能不是绝对必要的。

以上假设Post具有imageURL: URL属性。


让我们清理一下:

let postsWithImages = postsRepository
    .fetchPosts()
    .flatMap { posts in
        Observable.combineLatest(
            posts
                .map { $0.imageURL }
                .map { URLSession.shared.rx.image(for: $0) }
            )
            .map { zip(posts, $0) }
    }
    .map { $0.map { (post: $0.0, image: $0.1) } }

以上需要一个新的函数:

extension Reactive where Base == URLSession {
    func image(for url: URL) -> Observable<UIImage?> {
        return data(request: URLRequest(url: url))
            .map { UIImage(data: $0) }
            .catchErrorJustReturn(nil)
    }
}

我想我会补充一些解释。正如我在文章中提到的, 在 RxSwift 中组合可观察量的配方,这里的魔力是使用 combineLatest[Observable<T>]转换为Observable<[T]>

运算符获取 Observable 数组,订阅所有可观察量,等待它们全部完成,然后发出一个事件,其中包含收集的所有值的数组。(之后,每次更新其中一个项目时,它都会发出一个新数组,但这在这里无关紧要。

最新更新