通常來說爷肝,一個序列如果發(fā)出了 error 或者 completed 事件宇智,那么所有內(nèi)部資源都會被釋放垮抗。如果你需要提前釋放這些資源或取消訂閱的話,那么你可以對返回的 可被清除的資源(Disposable) 調用 dispose 方法:
var disposable: Disposable?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.disposable = textField.rx.text.orEmpty
.subscribe(onNext: { text in print(text) })
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.disposable?.dispose()
}
調用 dispose 方法后惩妇,訂閱將被取消株汉,并且內(nèi)部資源都會被釋放。通常情況下歌殃,你是不需要手動調用 dispose 方法的乔妈,這里只是做個演示而已。我們推薦使用 清除包(DisposeBag) 或者 takeUntil 操作符 來管理訂閱的生命周期氓皱。
DisposeBag
因為我們用的是 Swift 路召,所以我們更習慣于使用 ARC 來管理內(nèi)存勃刨。那么我們能不能用 ARC 來管理訂閱的生命周期了。答案是肯定了股淡,你可以用 清除包(DisposeBag) 來實現(xiàn)這種訂閱管理機制:
var disposeBag = DisposeBag()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
textField.rx.text.orEmpty
.subscribe(onNext: { text in print(text) })
.disposed(by: self.disposeBag)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.disposeBag = DisposeBag()
}
當 清除包 被釋放的時候身隐,清除包 內(nèi)部所有 可被清除的資源(Disposable) 都將被清除。
在輸入驗證中我們也多次看到 清除包 的身影:
var disposeBag = DisposeBag() // 來自父類 ViewController
override func viewDidLoad() {
super.viewDidLoad()
...
usernameValid
.bind(to: passwordOutlet.rx.isEnabled)
.disposed(by: disposeBag)
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
passwordValid
.bind(to: passwordValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
everythingValid
.bind(to: doSomethingOutlet.rx.isEnabled)
.disposed(by: disposeBag)
doSomethingOutlet.rx.tap
.subscribe(onNext: { [weak self] in self?.showAlert() })
.disposed(by: disposeBag)
}
這個例子中 disposeBag 和 ViewController 具有相同的生命周期唯灵。當退出頁面時贾铝, ViewController 就被釋放,disposeBag 也跟著被釋放了埠帕,那么這里的 5 次綁定(訂閱)也就被取消了垢揩。這正是我們所需要的。
takeUntil
另外一種實現(xiàn)自動取消訂閱的方法就是使用 takeUntil 操作符敛瓷,上面那個輸入驗證的演示代碼也可以通過使用 takeUntil 來實現(xiàn):
override func viewDidLoad() {
super.viewDidLoad()
...
_ = usernameValid
.takeUntil(self.rx.deallocated)
.bind(to: passwordOutlet.rx.isEnabled)
_ = usernameValid
.takeUntil(self.rx.deallocated)
.bind(to: usernameValidOutlet.rx.isHidden)
_ = passwordValid
.takeUntil(self.rx.deallocated)
.bind(to: passwordValidOutlet.rx.isHidden)
_ = everythingValid
.takeUntil(self.rx.deallocated)
.bind(to: doSomethingOutlet.rx.isEnabled)
_ = doSomethingOutlet.rx.tap
.takeUntil(self.rx.deallocated)
.subscribe(onNext: { [weak self] in self?.showAlert() })
}
這將使得訂閱一直持續(xù)到控制器的 dealloc 事件產(chǎn)生為止叁巨。
注意??:這里配圖中所使用的 Observable 都是“熱” Observable,它可以幫助我們理解訂閱的生命周期呐籽。