美文网首页
当PublishSubject遇到UITableview复用机制

当PublishSubject遇到UITableview复用机制

作者: 桔子听 | 来源:发表于2018-07-02 10:58 被阅读7次

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

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

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

    var row: Int?
    var deletePulish = PublishSubject<Int>()
    

    点击删除,将传入的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<Int>(),将删除的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<Int>()
                    self?.users.remove(at: row)
                    if let users = self?.users {
                        self?.usersRelay.accept(users)
                    }
                }).disposed(by: self.disposeBag)
                
                }
                .disposed(by: disposeBag)
    

    相关文章

      网友评论

          本文标题:当PublishSubject遇到UITableview复用机制

          本文链接:https://www.haomeiwen.com/subject/dqpkuftx.html