1

I'm trying to implement Kingfisher prefetch feature inside an Rxswift project. The problem is with these 2 function

collectionView.rx.prefetchItems
collectionView.rx.cancelPrefetchingForItems

The instruction at Kingfisher github is quite short

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()
    }
}

How can we implement with Rxswift? anyway to get the models and then the urls of models from array of indexpath. Thank.

4

1 回答 1

3

我将引导您了解我是如何找到解决方案的,以帮助您找出未来的解决方案......

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

首先,我们知道当发送一个事件时需要发生一些事情,prefetchItemsAt所以我们从这个开始:

let foo = collectionView.rx.prefetchItems

现在检查 的类型foo以查看它是否为ControlEvent<[IndexPath]>. ControlEvent 是一种可观察的。我们只需要itemsIndexPaths 的一部分,所以让我们map这样做:

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

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

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

withLatestFrom就像它只在主要可观察对象发出值时触发,combineLatest而不是在次要可观察对象发出值时触发。

现在,检查 的类型foo会发现它是一个 Observable 的 Items 数组。我们要发送到 ImagePrefetcher 的确切项目的 url。所以我们需要将 urlStrings 提取到 URLs 中。

    (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)

最后一点让一切都变得干净......如果你有的话,可以将 和 之间prefetchItems的所有东西subscribe移到 ViewModel 中。

这里的关键点是您可以使用类型来指导您,并且您需要知道哪些操作符可用于操作 Observables,您可以在http://reactivex.io/documentation/operators.html找到这些操作符

于 2018-10-14T14:37:18.927 回答