Igor Kulman
Igor Kulman

Reputation: 16359

Deleting multiple UITableView items with RxSwift does not work with a custom cell

I have a UITableView where I bind items using RxSwift. Simplified code may look like this, just a Variable holding an array

let data = Variable<[Int]>([1,2,3,4])

bound to the UITableView

tableView.register(GroupCell.self)

data.asObservable().bindTo(tableView.rx.items) { tableView, row, group in
        let indexPath = IndexPath(row: row, section: 0)
        let cell = tableView.dequeueReusableCell(GroupCell.self, indexPath: indexPath)
        return cell
        }
        .disposed(by: disposeBag)

I delete the items using

tableView.rx.itemDeleted.subscribe(onNext: { [unowned self] indexPath in self.data.value.remove(at: indexPath.row)}).disposed(by: disposeBag)

The problem is that deleting the first item works, but deleting a second item in the same position does not. The delete button just does not show

enter image description here

If I tap the delete icon on another row, the delete button shows. It just does not show in the "position" of previously deleted item.

Update: I found out it only happens when I use a custom cell. Does not happen with a simple StoryBoard cell.

Upvotes: 0

Views: 2451

Answers (2)

Igor Kulman
Igor Kulman

Reputation: 16359

The problem was the actual cell class. I use RxSwift in in to bind a ViewModel to the UI and this code was the cause

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

I thought it was a good idea to dispose all the binding before the cell gets recycled. I do not know why this causes the problem but disposing the bag before assigning a new ViewModel seems to work.

Upvotes: 0

Daniel T.
Daniel T.

Reputation: 33979

The code below works fine. Maybe your problem is elsewhere?

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.isEditing = true

        data.asObservable().bind(to: tableView.rx.items) { tableView, row, group in
            let indexPath = IndexPath(row: row, section: 0)
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell.textLabel?.text = "\(group)"
            return cell
        }
        .disposed(by: bag)

        tableView.rx.itemDeleted
            .subscribe(onNext: { [unowned self] indexPath in
                self.data.value.remove(at: indexPath.row)
            })
            .disposed(by: bag)
    }

    let data = Variable<[Int]>([1,2,3,4])
    let bag = DisposeBag()
}

Upvotes: 2

Related Questions