上次分析了deallocating和deallocated,除了這兩個是否還有別的,好像并沒有汹忠。如果沒有炮车,那我們就模仿寫出來,擴展Rx的能力。比如下面的例子:
extension Reactive where Base: UITableViewCell {
public var prepareForReuse: RxSwift.Observable<Void> {
var prepareForReuseKey: Int8 = 0
if let prepareForReuseOB = objc_getAssociatedObject(base, &prepareForReuseKey) as? Observable<Void> {
return prepareForReuseOB
}
let prepareForReuseOB = Observable.of(
sentMessage(#selector(Base.prepareForReuse)).map { _ in }
, deallocated)
.merge()
objc_setAssociatedObject(base, &prepareForReuseKey, prepareForReuseOB, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
return prepareForReuseOB
}
public var reuseBag: DisposeBag {
MainScheduler.ensureExecutingOnScheduler()
var prepareForReuseBag: Int8 = 0
if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag {
return bag
}
let bag = DisposeBag()
objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
_ = sentMessage(#selector(Base.prepareForReuse))
.subscribe(onNext: { [weak base] _ in
let newBag = DisposeBag()
guard let base = base else {return}
objc_setAssociatedObject(base, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
})
return bag
}
}
我們使用RxSwift和UITableView
的同時,可能會遇到重用和內(nèi)存之間的問題,上面的例子就是為解決這個問題而寫的糠馆,比如rx.prepareForReuse
是為了監(jiān)聽cell
的prepareForReuse
,rx.reuseBag
是為了給cell
添加一個垃圾袋怎憋,都可以解決問題:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
cell.button.rx.tap
.takeUntil(cell.rx.prepareForReuse)
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
return cell
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
}).disposed(by: cell.rx.reuseBag)
return cell
}