PublishSubject
既是一个观察者,也是一个被观察者,通常用来代替delegate
。如下需求:
思路很简单,点击cell
里删除按钮,用PublishSubject
将删除事件回调给ViewController
,在ViewController
里删除数据源,再更新tableView
。
在cell
里定义属性,row
用定位数据源位置,这里情况特殊,数据源的index
和cell
的row
一一对应,传入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)