Search code examples
iosswiftrx-swiftrx-cocoa

Get model from UICollectionView indexpath


I'm using RxSwift to bind a model array to a collection view

How do I get the model object from a given indexPath?

I'm doing the binding like this:

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

The core of my issue is, that I need to get both the model object and the cell that a user selects. Using collectionView.rx.modelSelected(T.self) only gives me the model og type T. And calling collectionView.rx.itemSelected only gives me the selected 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)

But this gives me an error when trying to the the model at indexPath:

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

Just trying:

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

also gives me an error:

Ambiguous reference to member 'model(at:)'

SO... How to get both the model object and the cell that a user selects?


Solution

  • I could have done like RamwiseMatt proposed. Making a method on my ViewModel that takes the IndexPath and return the model. I did however end up using a 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()
                }