iOS Rxswift使用Kingfisher预取单元格图像

时间:2018-10-14 13:34:48

标签: rx-swift prefetch kingfisher

我正在尝试在Rxswift项目中实现Kingfisher预取功能。问题在于这两个功能

collectionView.rx.prefetchItems
collectionView.rx.cancelPrefetchingForItems

Kingfisher github上的指令很短

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView?.prefetchDataSource = self
}

extension ViewController: UICollectionViewDataSourcePrefetching {
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        let urls = indexPaths.flatMap { URL(string: $0.urlString) }
        ImagePrefetcher(urls: urls).start()
    }
}

我们如何使用Rxswift实现?无论如何要从models数组中获取urls的{​​{1}}和models的{​​{1}}。谢谢。

1 个答案:

答案 0 :(得分:3)

我将引导您逐步了解解决方案,以帮助您确定将来的解决方案...

我假设保存URL字符串的结构称为Item,并且您当前有一个Observable<[Item]>用于加载集合视图。我还假设您的收藏集中只有一个部分。

首先,我们知道prefetchItemsAt发送事件时需要发生一些事情,因此我们从此开始:

let foo = collectionView.rx.prefetchItems

现在检查foo的类型以确认它是ControlEvent<[IndexPath]>。 ControlEvent是一种可观察的事件。我们只需要IndexPaths的items部分,所以让map做到:

let foo = collectionView.rx.prefetchItems
    .map { $0.map { $0.item } }

(双重映射是Swift不支持更高种类的类型的不幸结果)现在检查foo的类型。它是一个可观察的整数数组。这些整数是我们项目数组的索引。因此,我们需要访问最近发出的项目:

    (as above)
    .withLatestFrom(items) { indexes, elements in
        indexes.map { elements[$0] }
    }

因此withLatestFromcombineLatest相似,只是它仅在主要可观察对象发出值时才触发,而不是在次要观察对象发出值时才触发。

现在,检查foo的类型将发现它是一个可观察的Items数组。我们要发送给ImagePrefetcher的确切网址对象。因此,我们需要将urlString提取到URL中。

    (as above)
    .map { $0.compactMap { URL(string: $0.urlString) } }

有了这个,我们有了我们希望ImagePrefetcher使用的URL数组。由于它消耗数据,因此需要将其包装在订阅块中。

    (as above)
    .subscribe(onNext: {
        ImagePrefetcher(urls: $0).start()
    })

在这一点上,foo是一次性的,因此只需将其收集在我们的处理袋中……这是完整的代码块。

collectionView.rx.prefetchItems
    .map { $0.map { $0.item } }
    .withLatestFrom(items) { indexes, elements in
        indexes.map { elements[$0] }
    }
    .map { $0.compactMap { URL(string: $0.urlString) } }
    .subscribe(onNext: {
        ImagePrefetcher(urls: $0).start()
    })
    .disposed(by: bag)

最后一点使所有内容变得干净... prefetchItemssubscribe之间的所有内容都可以移入ViewModel。

这里的主要要点是,您可以使用类型来指导您,并且需要知道哪些运算符可用于操作可观察的对象,您可以在http://reactivex.io/documentation/operators.html

中找到这些对象。