Как избежать дублирования нажатия на кнопку в Tableview с помощью RxDataSources

У меня есть табличное представление с RxDataSources, на котором элементы ячеек получили значок удаления. когда ячейки удаляются из очереди и щелкают этот значок удаления, запускаются все предыдущие события щелчка, таким образом дублируя нажатие. Ячейка товара:

 removeImageView.rx.tap().map { _ in indexPath } 
            .bind(to: viewModel.onRemoveItem).disposed(by: cellDisposeBag)

Модель просмотра ячеек:

let onRemoveItem = PublishSubject<IndexPath>()

Представьте модель представления контроллера, в которой привязаны ячейка и ViewModel:

 let vm = ItemViewModel(with: item)
            vm.onRemoveItem.bind(to: self.onRemoveItem).disposed(by: self.rx.disposeBag)

            return SectionItem.item(viewModel: vm)

Просмотр контроллера:

let dataSource = RxTableViewSectionedReloadDataSource<SectionItem>(configureCell: { dataSource, tableView, indexPath, item in
    switch item {
    case .item(let viewModel):
        let cell = (tableView.dequeueReusableCell(withIdentifier: itemtIdentifier, for: indexPath) as? ItemCell)!
        cell.bind(to: viewModel, at: indexPath)
        return cell
    }
}, titleForHeaderInSection: { dataSource, index in
    let section = dataSource[index]
    return section.title
}  )

output?.items
    .bind(to: tableView.rx.items(dataSource: dataSource))
    .disposed(by: rx.disposeBag)

output?.onRemoveCartIemTapped.distinctUntilChanged() 
    .skip(1)
    .distinctUntilChanged().drive(onNext: { [weak self] (indexPath) in
    print("onRemoveCartIemTapped" + String(indexPath.item))
}).disposed(by: rx.disposeBag)

Консольная отладка:

onRemoveCartIemTapped0
onRemoveCartIemTapped3
onRemoveCartIemTapped1
onRemoveCartIemTapped4

person Mohamed ALOUANE    schedule 02.01.2019    source источник
comment
У вас есть для этого образец проекта? Я бы хотел помочь вам в этом. Это должно быть довольно просто, но я обычно использую обычную реализацию делегатов и методов источника данных tableView в моей модели ViewModel без использования расширений RxSwift (но с использованием RxSwift во всем проекте, а не только в tableViews).   -  person Glenn Posadas    schedule 02.01.2019
comment
Вы удаляете cellDisposeBag в prepareForReuse методе ячейки? Если ячейки повторно используются без удаления подписок, это может вызвать такое поведение.   -  person Paul    schedule 02.01.2019
comment
нет, я вообще не использую prepareForReuse. как я могу это сделать, даже если у меня есть ячейка, которая удаляется при нажатии кнопки   -  person Mohamed ALOUANE    schedule 02.01.2019
comment
@Paul Я исправил, спасибо :). оставьте свой комментарий в качестве ответа.   -  person Mohamed ALOUANE    schedule 02.01.2019


Ответы (1)


Это вызвано UITableView повторным использованием ячейки. Чтобы избежать множественных подписок, вы можете переопределить метод prepareForReuse() ячейки и обеспечить удаление всех существующих подписок.

Обычно я объявляю DisposeBag как var, а затем назначаю ему новый DisposeBag в prepareForReuse(). Когда DisposeBag деиницируется, он удалит все содержащиеся в нем подписки. Что-то типа:

override func prepareForReuse() {
    super.prepareForReuse()

    cellDisposeBag = DisposeBag()
}
person Paul    schedule 03.01.2019
comment
Когда DisposeBag деиницируется ‹- когда это происходит? - person Honey; 10.05.2019