当PublishSubject遇到UITableview复用机制

PublishSubject既是一个观察者,也是一个被观察者,通常用来代替delegate。如下需求:

思路很简单,点击cell里删除按钮,用PublishSubject将删除事件回调给ViewController,在ViewController里删除数据源,再更新tableView

cell里定义属性,row用定位数据源位置,这里情况特殊,数据源的indexcellrow一一对应,传入row,相当于数据源的index,到时候回调出去,就知道删除哪条数据:

var row: Int?
var deletePulish = PublishSubject()

点击删除,将传入的row回调出去:

btnDelete.rx.tap.subscribe(onNext: { [weak self] in
            if let row = self?.row {
                self?.deletePulish.onNext(row)
            }
        }).disposed(by: disposeBag)

ViewController里:

usersRelay.bind(to: tbl.rx.items(cellIdentifier: "SelectedMemberCell", cellType: SelectedMemberCell.self)) { (row, element, cell) in
            cell.lblName.text = element.userName
            cell.row = row
            cell.deletePulish.subscribe(onNext: { [weak self] row in
                self?.users.remove(at: row)
                if let users = self?.users {
                    self?.usersRelay.accept(users)
                }
            }).disposed(by: self.disposeBag)
            
            }
            .disposed(by: disposeBag)

以上都是很正常的用法。

这里隐藏了一个问题。
我点击删除孟浩然,正常。
我再点击删除杜甫,却删除了杜甫和李白两条。

经过调试,发现,cell的点击删除事件的确只发触发一次,onNext发送删除事件也只有一次。

但是ViewController里订阅事件的确执行了两次。那么问题就在于为什么发送一次,会接收两次?

只有一种可能,就是有两个对象订阅了同一个事件。

经过增加更多的数据发现规律,点一次删除一条,再点一次删除两条,第三次删除三条。。。。。。很显然,之前被删除的cell依然再接收事件。所以,问题在于,之前的cell虽然从数据源上删除了,导致不显示,但是cell本身并没有dealloc,也就是还在内存里,依然会接收事件。

ViewController里加上一句cell.deletePulish = PublishSubject(),将删除的cell里的订阅者重新赋值,就不会再接收到事件,如果deletePulish定义为可选类型,那么可以直接设为cell.deletePulish = nil

usersRelay.bind(to: tbl.rx.items(cellIdentifier: "SelectedMemberCell", cellType: SelectedMemberCell.self)) { (row, element, cell) in
            cell.lblName.text = element.userName
            cell.row = row
            cell.deletePulish.subscribe(onNext: { [weak self] row in
                cell.deletePulish = PublishSubject()
                self?.users.remove(at: row)
                if let users = self?.users {
                    self?.usersRelay.accept(users)
                }
            }).disposed(by: self.disposeBag)
            
            }
            .disposed(by: disposeBag)

你可能感兴趣的:(当PublishSubject遇到UITableview复用机制)