How to reload UITableView by use RxDataSources correctly?

916 views Asked by At

I'm trying to build a tableView witch has many cells with a button, what I want to do is when I click the button in a cell, the cell should be go to the bottom of the table, here's my code:

let datasource = RxTableViewSectionedAnimatedDataSource<ToDoListSection>(
            configureCell: { [weak self] _, tableView, indexPath, item in
                guard let self = self else { return UITableViewCell() }
                let cell = tableView.dequeueReusableCell(withIdentifier: ToDoTableViewCell.reuseID, for: indexPath) as? ToDoTableViewCell
                cell?.todoTextView.text = item.text
                cell?.checkBox.setSelect(item.isSelected)
                cell?.checkBox.checkBoxSelectCallBack = { selected in
                    if selected {
                        var removed = self.datasList[indexPath.section].items.remove(at: indexPath.row)
                        removed.isSelected = selected
                        self.datasList[indexPath.section].items.append(removed)
                        self.datasList[indexPath.section] = ToDoListSection(
                            original: self.datasList[indexPath.section],
                            items: self.datasList[indexPath.section].items
                        )
                        self.sections.onNext(datasList)
                    } else {
                        // Todo
                    }
                }
                return cell ?? UITableViewCell()
            }, titleForHeaderInSection: { dataSource, section in
                return dataSource[section].header
            })
        
        sections.bind(to: table.rx.items(dataSource: datasource))
            .disposed(by: disposeBag)

however, because I sent a onNext event in the configureCell closure, I received a waring:

⚠️ Reentrancy anomaly was detected.

Debugging: To debug this issue you can set a breakpoint in /Users/me/Desktop/MyProject/Pods/RxSwift/RxSwift/Rx.swift:96 and observe the call stack. Problem: This behavior is breaking the observable sequence grammar. next (error | completed)? This behavior breaks the grammar because there is overlapping between sequence events. Observable sequence is trying to send an event before sending of previous event has finished. Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code, or that the system is not behaving in the expected way. Remedy: If this is the expected behavior this message can be suppressed by adding .observe(on:MainScheduler.asyncInstance) or by enqueuing sequence events in some other way.

and the action on the screen is not I want. what should I do? how to reload the TableView correctly?

1

There are 1 answers

0
Daniel T. On

The fundamental problem here is that you are calling onNext inside an Observer that is observing the emission. Another way to word this is that you are emitting a new value before the system is finished processing the current value.

As the warning says, the simplest way to deal with this (and likely the best way in this case) is to insert .observe(on:MainScheduler.asyncInstance) between sections. and bind(to:). What this does is stall the emission for a cycle so your configureCell function has a chance to return.