Двойное сопоставление RxSwift в tableView.rx.itemSelected

Я хочу получить объект от tableView.rx.itemSelected и обработать его. Этот метод возвращает IndexPath, поэтому я могу сопоставить это значение. Но как получить объект по индексу из ViewModel?

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

Приблизительно я ожидаю что-то вроде этого (но этот поток неверен):

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)

Я где-то показывал эту возможность, но не могу вспомнить. У вас есть идеи, как это сделать?


person biloshkurskyi.ss    schedule 02.10.2017    source источник
comment
Почему бы вам просто не вернуть viewModel.items[indexPath.row] в функцию map?   -  person Nikita Ermolenko    schedule 02.10.2017
comment
@NikitaErmolenko В этом случае я получаю сообщение об ошибке: тип 'Observable‹[Item]›' не имеет элементов нижнего индекса   -  person biloshkurskyi.ss    schedule 03.10.2017
comment
Какой тип viewModel.items?   -  person Nikita Ermolenko    schedule 03.10.2017
comment
Это: var items: Observable‹[Item]›   -  person biloshkurskyi.ss    schedule 03.10.2017


Ответы (3)


Если вам нужны как indexPath, так и model, вы можете объединить 2 метода и преобразовать их только в одну наблюдаемую последовательность:

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)
person Eduard    schedule 09.01.2018
comment
не является оптимальным решением, потому что stackoverflow.com/a/60926473/7104327 здесь - person headstream; 30.03.2020

RxCocoa имеет 2 метода:

public var itemSelected: ControlEvent<IndexPath> { get } который возвращает IndexPath выбранного элемента
и
public func modelSelected<T>(_ modelType: T.Type) -> ControlEvent<T> который возвращает элемент модели
В соответствии с вашим примером это будет выглядеть:

    tableView.rx.modelSelected(Item.self)
        .subscribe(onNext: { [weak self] item in
            // other actions with Item object
        }).addDisposableTo(disposeBag)
person Ihar Katkavets    schedule 04.10.2017
comment
Спасибо за ваш комментарий. Вы правы насчет 2 потока. Я использовал его, но я хочу улучшить свое понимание. Поэтому запрашивается обработка itemSelected. - person biloshkurskyi.ss; 04.10.2017

Также я нашел другой способ добавить do(onNext:{...}) после команды itemSelected:

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)
person biloshkurskyi.ss    schedule 27.03.2019