swiftrx-swiftrxdatasources

Why UITableViewCell does not bind to cellWiewModel when I use RxTableViewSectionedAnimatedDataSource?


I have some odd problem with UITableViewCell when I use MVVM pattern with RxSwift. I can't describe it, but I will try to explain.

Let's say we have simple UITableViewCell

class MyTableViewCell: UITableViewCell {
  var disposeBag = DisposeBag()

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

func bind(to viewModel: MyCellViewModel) {
    viewModel.randomValue.asDriver()
      .drive(onNext: { [weak self] value in
        guard let self = self else { return}
        print(value) // WHEN TWO CELLS I GET NEW VALUES JUST IN ONE OF THEM
      })
      .disposed(by: disposeBag)
    
}

with ViewModel with simple timer.

class MyCellViewModel: NSObject {
  let randomValue = PublishSubject<Int>()
  init() {

 Observable<Int>.timer(.seconds(1), period: .seconds(1), scheduler: SerialDispatchQueueScheduler(qos: .userInteractive))
        .map { _ in Int.random()}
        .do(onNext: {
          print($0) // WORK PERFECT FOR BOTH
        })
        .bind(to: randomValue)
        .disposed(by: rx.disposeBag)
 }

}

I also use RxDataSources to fill my tableView.

   private func makeDataSource() -> RxTableViewSectionedAnimatedDataSource<Section> {
        RxTableViewSectionedAnimatedDataSource<Section>(configureCell: { _, tableView, indexPath, item in
          switch item {
          case let .myItem(cellViewModel):
            let cell = tableView.dequeueReusableCell(with: MyTableViewCell.self, for: indexPath)
            cell.bind(to: cellViewModel)
            return cell
          }
        })
      }

The problem is that when I have two cells, I get new values in one of them and not in the other.

Pay attention to the method bind(to viewModel

But everything is ok when I change RxTableViewSectionedAnimatedDataSource to RxTableViewSectionedReloadDataSource.

How to make it work with RxTableViewSectionedAnimatedDataSource? I understand the difference between them, but in this case I don't know how does that affect it?

I also checked memory graph and saw just two instances of cells and two instances of cellViewModels. So I hope there are no leaks.

Thanks for any help!


Solution

  • You implemented your ItemMode.== incorrectly. It doesn't actually check for equality, it only checks the identity. Remove the function and let the compiler generate the correct one for you.