RxSwift double mapping in tableView.rx.itemSelected
Asked Answered
C

3

12

I want to get object from tableView.rx.itemSelected and after process it. This method return IndexPath, so I can map this value. But how to get object at index from the ViewModel?

struct ViewModel {
    var items: Observable<[Item]>
}

Approximate I expect something like this (but this flow is wrong):

tableView.rx.itemSelected
        .map { indexPath -> Item in 
        return viewModel.items.map {$0[indexPath.row]}
        }
        ..subscribe(onNext: { [unowned self] item in
        //other actions with Item object
        })
        .disposed(by: disposeBag)

I showed somewhere this possibility, but cant recollect it. Have you some idea how to do it?

Cosmic answered 2/10, 2017 at 7:20 Comment(4)
Why don't you just return viewModel.items[indexPath.row] in map function?Network
@NikitaErmolenko In this case I get error: Type 'Observable<[Item]>' has no subscript membersCosmic
What type of viewModel.items?Network
It is: var items: Observable<[Item]>Cosmic
P
41

If you need both indexPath and the model you could combine the 2 methods and transform them in only one observable sequence:

Observable
    .zip(tableView.rx.itemSelected, tableView.rx.modelSelected(String.self))
    .bind { [unowned self] indexPath, model in
        self.tableView.deselectRow(at: indexPath, animated: true)
        print("Selected " + model + " at \(indexPath)")
    }
    .disposed(by: disposeBag)
Passkey answered 9/1, 2018 at 15:6 Comment(1)
is not optimal solution, because https://mcmap.net/q/909472/-get-model-from-uicollectionview-indexpath HereWeatherworn
P
10

RxCocoa has 2 methods:

public var itemSelected: ControlEvent<IndexPath> { get } which returns IndexPath of selected item
and
public func modelSelected<T>(_ modelType: T.Type) -> ControlEvent<T> which returns the model element
In accordance to your example it will look:

    tableView.rx.modelSelected(Item.self)
        .subscribe(onNext: { [weak self] item in
            // other actions with Item object
        }).addDisposableTo(disposeBag)
Patrilineal answered 4/10, 2017 at 8:11 Comment(1)
Thanks for your comment. You are right about 2nd flow. I have used it but I want to increase my understanding. Therefore itemSelected processing is asked.Cosmic
C
2

Also I have found other way add do(onNext:{...}) after itemSelected command:

tableView.rx
    .itemSelected
    .do(onNext: { [unowned self] indexPath in
        self.tableView.deselectRow(at: indexPath, animated: false)
    })
    .map { indexPath -> Item in 
        return viewModel.items.map {$0[indexPath.row]}
    }
    .subscribe(self.viewModel.reviewTimeAction.inputs)
    .disposed(by: disposeBag)
Cosmic answered 27/3, 2019 at 21:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.