从 UICollectionView 索引路径获取模型

Posted

技术标签:

【中文标题】从 UICollectionView 索引路径获取模型【英文标题】:Get model from UICollectionView indexpath 【发布时间】:2017-10-18 13:41:56 【问题描述】:

我正在使用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 的模型时,这给了我一个错误:

类型“inout UICollectionView”不符合协议 '反应兼容'

只是尝试:

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

也给了我一个错误:

对成员'model(at:)'的模糊引用

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

【问题讨论】:

【参考方案1】:

我本可以像 RamwiseMatt 提议的那样做。在我的 ViewModel 上创建一个采用 IndexPath 并返回模型的方法。然而我最终还是使用了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()
            

【讨论】:

【参考方案2】:

你自己接受的解决方案不是最优的,因为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)
        

【讨论】:

【参考方案3】:

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

我不知道你为什么还要引用你的单元格,但如果你必须,你可以在你的UICollectionView 上使用cellForItem(at:)(将你通过itemSelected 获得的IndexPath 提供给它。)

【讨论】:

以上是关于从 UICollectionView 索引路径获取模型的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 uicollectionview 的最后一个索引路径?

使用点击手势时如何获取 UICollectionView 标头的索引路径?

UICollectionView:页面控件的当前索引路径

UICollectionView接收具有不存在的索引路径的单元格的布局属性

将 UILabel 添加到 UICollectionView 中的特定索引路径

默认情况下,如何选择 UICollectionView 的特定索引路径?