从 UICollectionView 索引路径获取模型

Get model from UICollectionView indexpath

我正在使用 RxSwift 将模型数组绑定到集合视图

如何从给定的 indexPath 获取模型对象?

我是这样绑定的:

vm.bikeIssueCatagories()
        .drive(self.collectionView.rx.items(cellIdentifier: "BikeIssueCategoryCollectionViewCell", cellType: UICollectionViewCell.self)) { row, data, cell in
        }.disposed(by: disposeBag)

我的问题的核心是,我需要同时获取模型对象和用户选择的单元格。使用 collectionView.rx.modelSelected(T.self) 只给我模型 og 类型 T。调用 collectionView.rx.itemSelected 只会给我选择的 IndexPath

collectionView.rx.itemSelected.asDriver()
        .driveNext { [unowned self] indexPath in
            guard let model = try? collectionView.rx.model(at: indexPath) else { return }
            guard let cell = self.collectionView.cellForItem(at: indexPath) else { return }
        }.disposed(by: disposeBag)

但是当我尝试在 indexPath:

处的模型时,这给了我一个错误

Type 'inout UICollectionView' does not conform to protocol 'ReactiveCompatible'

正在尝试:

let indexPath = IndexPath.init()
self.collectionView.rx.model(at: indexPath)

也给我一个错误:

Ambiguous reference to member 'model(at:)'

SO...如何同时获取模型对象和用户选择的单元格?

您的 ViewModel 定义了一个方法 bikeIssueCatagories(),这是您的 UIViewController 将 UICollectionView 绑定到的方法。为了让您的模型处于正确的位置,您可以使用您提到的 itemSelected 属性,这会给您一个 Observable<IndexPath>,您应该将其输入您的 ViewModel。在那里,您可以使用 IndexPath 的 item 属性 来确定您要查找的数据数组(在 bikeIssueCatagories() 中给出)中的哪个模型。 modelSelected 属性 使这对您来说更容易,因为它已经知道数据源,因此您只需提供模型的类型(将 T.self 替换为 YourModelName.self。)

我不确定您为什么还要引用您的单元格,但如果必须的话,您可以在 UICollectionView 上使用 cellForItem(at:)(将您通过itemSelected.)

我本可以像 RamwiseMatt 提议的那样做。在我的 ViewModel 上制作一个采用 IndexPath 和 return 模型的方法。但是我确实最终使用了 zip:

let modelSelected = collectionView.rx.modelSelected(SelectableBikeIssueCategory.self).asObservable()

let cellSelected = collectionView.rx.itemSelected.asObservable()
            .map { [weak self] indexPath -> UICollectionViewCell in
                guard let cell = self?.collectionView.cellForItem(at: indexPath) else { fatalError("Expected cell at indexpath") }
                return cell
            }

Observable.zip(cellSelected, modelSelected)
            .map { [weak self] cell, category -> SomeThing in
                return SomeThing()
            }

你自己接受的方案不是最优的,因为modelSelected流内部映射了indexPath,需要在不需要知道indexPath的时候使用。在您的情况下,最好使用 itemSelected 并转换为元组。

 collectionView.rx.itemSelected
    .map { [weak self] indexPath in
            guard
               let model = try? self?.collectionView.rx.model(at: indexPath) as YourModelName?,
               let cell = self?.collectionView.cellForItem(at: indexPath)  
            else {
                preconditionFailure("Describing of error")
            }


            return (cell, model)
        }