self -> myClosure -> {} -> self -釋放不掉
bash
myClosure = {() in
//// weak - strong - dance
DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
self.name = "ABC"
print(self.name)
})
}
self.myClosure!()
複製代碼
上面的代碼會產生循環引用釋放不掉,解決辦法:閉包
[weak self]
[unowned self]
guard let self = self else { return }
那是否是全部的閉包裏面引用self
就會產生循環引用? 答案是NO
,必定要構成循環引用圈纔會async
經過RxSwift.Resources.total
的引用計數檢測是否釋放: 在ViewController
裏有下列代碼:ide
在HomeViewController
裏有下列代碼:性能
ViewController
沒有釋放,那是由於
self.title = text
的時候產生了循環引用,這個時候加個
[weak self]
就解決了:
self -> observable
-> 建立閉包 -> self
即create閉包引用self會產生循環引用ui
self -> observable
-> subscribe閉包 -> self
即訂閱閉包引用self也會產生循序引用spa
self -> disposeBag -> insert -> dispose -> sink -> observer
<- self
即咱們在保存訂閱者的時候不會產生循環使用self -> observer -> observer = AnonymousObservableSink.on() -> AnonymousObservableSink._observer.on -> AnonymousObserver.on -> _eventHandler -> onNext閉包 -> self
即咱們在訂閱流程裏打印self
也會產生循環引用會產生引用計數的不斷增長
error
,completed
回收,若是下次想用,在進行激活TableViewCell
上button
點擊複用的問題let bag = DisposeBag()
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! LGTableViewCell
cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
.disposed(by: bag)
return cell
}
複製代碼
上面的代碼會有什麼問題呢?code
那怎麼會出現上面這種狀況呢,明明已經.disposed(by: bag)
了,怎麼還會重用呢,注意:這裏的bag
的生命週期是伴隨viewController
的,這裏使用bag
天然就沒有任何效果cdn
猜測,那使用vc
的bag
不能夠,那咱們能夠直接使用cell
的bag
麼,以下:server
//cell裏邊
var disposeBag = DisposeBag()
//vc裏邊
cell.button.rx.tap
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
.disposed(by: cell.disposeBag)
複製代碼
運行代碼:
仍是沒有解決,這是爲啥呢,緣由是咱們的cell
滾動過程並無走deinit
,天然也就不會銷燬,所以,即使有disposeBag
,不銷燬任然也是沒有用的
那咱們vc
裏重用隊列裏取cell
的地方加上cell.disposeBag = DisposeBag()
,能解決問題麼
cell.disposeBag
,滾動的過程也在不斷建立,浪費資源,浪費性能
那要怎樣才能解決該問題呢?
cell.disposeBag
,能完美解決問題尚未上面的問題就行了,那咱們能夠在cell
的內部重寫prepareForReuse
的時候初始化disposeBag
就能完美解決問題了//cell 準備重用的方法
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
複製代碼
takeUntil
並擴展一個rx
的prepareForReuse
方法 來解決問題cell.button.rx.tap.takeUntil(cell.rx.prepareForReuse)
.subscribe(onNext: { () in
print("點擊了 \(indexPath)")
})
複製代碼
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
}
// sentMessage 響應方法執行以前
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
}
}
複製代碼