如何使用 RxSwift disposeBag 防止 UITableViewCell 中重复的 UIButton 点击

Posted

技术标签:

【中文标题】如何使用 RxSwift disposeBag 防止 UITableViewCell 中重复的 UIButton 点击【英文标题】:How to prevent duplicate UIButton taps in UITableViewCell with RxSwift disposeBag 【发布时间】:2017-10-24 10:51:29 【问题描述】:

首先对令人困惑的标题感到抱歉,但实际上我想不出更好的东西(如果有,请编辑)。

我有一个使用 Coordinator 模式和 RxSwift 的应用程序,所以总而言之,我希望将所有与 导航 相关的东西传递给 Coordinator,以便它可以处理导航逻辑。 在一个视图控制器中,我有UITableView,其中包含UIButton 的单元格。对于这种情况,我有一个:

actionButton.rx.tap.bind(to: viewModel.chapterAction).disposed(by: disposeBag)

chapterAction 是一个PublishSubject<Void>,因为它只反映了一个按钮点击,但我需要将更多信息传递给 Coordinator,所以稍后我将这个 chapterAction 转换为:

var showChapter: Observable<Chapter> = self.chapterAction.mapTo(self.chapter)

假设到目前为止,这段代码没有任何问题,所以在 View Controller 的 .bind(to: tableView.rx.items... 中我有:

viewModel.showChapter.bind(to: self.viewModel.chapterAction).disposed(by: viewModel.disposeBag)

因为我想将此绑定到视图控制器的 viewModel 和后来的 subscribe 在协调器中。 一切正常,但是对于某些单元格,我得到重复点击,为什么?我试过把distinctUntilshareReply,但似乎没有任何帮助我的问题,它不是一个确定性的问题。我怀疑涉及到一些重用,但我不知道从哪里开始寻找这个问题......

【问题讨论】:

【参考方案1】:

需要在prepareForReuse()方法中重新初始化disposeBag

override func prepareForReuse() 
    super.prepareForReuse()
    disposeBag = DisposeBag()

然后,所有以前的订阅都被释放。

【讨论】:

不是这种情况 - 我正在重新初始化,但仍然重复。虽然,我的代码示例说我使用 viewModel 中的 dispose bag 我实际上尝试了我可以从这个地方访问的每个 dispose bag - cell、viewModel、view controller 的【参考方案2】:

我仍然不知道我的代码到底出了什么问题,但我最终在tableView.rx.items 绑定块中直接添加了mapTo。现在看起来像这样:

viewModel.chapterCellViewModels
    .bind(to: tableView.rx.items(cellIdentifier: ChapterCell.nameOfClass, cellType: ChapterCell.self ))  (_, viewModel, cell) in
        cell.configureCell(with: viewModel)

        cell.actionButton.rx.tap
            .mapTo(viewModel.chapter)
            .bind(to: self.viewModel.chapterAction)
            .disposed(by: cell.disposeBag)
    
    .disposed(by: disposeBag)

正如我在 OP 中提到的 - 我猜这是由于某些重用等原因,但我无法回答为什么会发生这种情况。

【讨论】:

以上是关于如何使用 RxSwift disposeBag 防止 UITableViewCell 中重复的 UIButton 点击的主要内容,如果未能解决你的问题,请参考以下文章

ViewController 中的 RxSwift DisposeBag 使用

RxSwift:当类具有 disposeBag 属性时,始终使用 [unowned self] 是不是安全?

在 RxSwift 中手动处理 DisposeBag

RxSwift:disposed(by: disposeBag) 真的有效吗?

如何使用 RxSwift Observable<Int>.interval?

RxSwift 系列