目錄
垃圾袋移除通知訂閱關(guān)系
賦值新的垃圾袋會(huì)讓之前垃圾袋綁定的訂閱關(guān)系釋放
用來(lái)給timer停止
demo下載地址
前言:前端時(shí)間學(xué)習(xí)了一下RxSwift框架,全學(xué)完以后再回過(guò)頭來(lái)發(fā)現(xiàn),后來(lái)理解的垃圾袋和最開(kāi)始時(shí)候不一樣,今天稍微總結(jié)一下
垃圾袋移除通知訂閱關(guān)系
let disposeBag = DisposeBag() //成員變量
override func viewDidLoad() {
super.viewDidLoad()
let UserNoti1 = "UserNoti1"
NotificationCenter.default.rx.notification(Notification.Name(UserNoti1)).subscribe(onNext: { (noti) in
print(Self.self,#function)
print("接收到通知noti=",noti)
})
.disposed(by: disposeBag)//注意,如果讓當(dāng)前控制器退出以后,讓其他頁(yè)面發(fā)送的通知可以接收到,這里就不能加垃圾袋,否則通知就被釋放了
}
注意看這個(gè)通知在控制器viewDidLoad以后就添加了通知,因?yàn)榻Y(jié)尾有垃圾袋 .disposed(by: disposeBag),這里的disposeBag 是成員變量,如果當(dāng)前控制器消失以后,disposeBag也消失,那么通知就被釋放了,原因是,通知的訂閱關(guān)系被綁定在成員變量上面,當(dāng)成員變量釋放,訂閱關(guān)系也沒(méi)了.所以這個(gè)通知只能被當(dāng)前控制器內(nèi)發(fā)出的通知接收到,其他控制器發(fā)出的通知不能接收到.
@IBAction func btnPostNoti(_ sender: Any) {
NotificationCenter.default.post(name: NSNotification.Name(UserNoti1), object: nil)
}
這個(gè)按鈕操作發(fā)送了通知,在當(dāng)前控制器內(nèi)按下按鈕可以被接收到.但是如果在其他控制器里想要接受到通知,必須把上面代碼的 .disposed(by: disposeBag) 去掉,這樣監(jiān)聽(tīng)的關(guān)系不會(huì)被釋放.
賦值新的垃圾袋會(huì)讓之前垃圾袋綁定的訂閱關(guān)系釋放
看下面代碼,有3個(gè)按鈕,前1個(gè)按鈕綁定了成員變量的垃圾袋,第二個(gè)按鈕綁定了臨時(shí)變量垃圾袋,第3個(gè)按鈕沒(méi)有綁定垃圾袋, 當(dāng)給成員變量的垃圾袋賦值新的值的時(shí)候,按鈕1,因?yàn)榻壎死?而且垃圾袋被賦值了新的值,那么之前綁定的值就被釋放了,所以按鈕1的訂閱點(diǎn)擊事件也失效了.第3個(gè)按鈕沒(méi)有綁定垃圾袋,所以點(diǎn)擊依然可以被訂閱到,按鈕2因?yàn)榻壎ǖ氖桥R時(shí)變量的垃圾袋,代碼剛執(zhí)行完ViewDidLoad訂閱關(guān)系就失效了
class VC1: UIViewController {
@IBOutlet weak var btn1: UIButton!
@IBOutlet weak var btn2: UIButton!
@IBOutlet weak var btn3: UIButton!
var disposeBag = DisposeBag()
deinit { print(Self.self,#function) }
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
btn1.rx.tap.subscribe { (btn) in
print("btn1點(diǎn)擊")
}.disposed(by: disposeBag)
btn2.rx.tap.subscribe { (btn) in
print("btn2點(diǎn)擊")
}.disposed(by: DisposeBag())//disposebag的作用就是:當(dāng)DisposeBag垃圾袋被釋放的時(shí)候,把它執(zhí)行的信號(hào)量也釋放,因?yàn)檫@里的是臨時(shí)變量創(chuàng)建的DisposeBag(),沒(méi)有被記錄成成員變量,出了viewDidLoad()方法之后就會(huì)被釋放.所以btn2的 點(diǎn)擊也被釋放了
btn3.rx.tap
.subscribe(onNext: { (btn) in
print("btn3點(diǎn)擊")
})
}
@IBAction func btn4Click(_ sender: Any) {
disposeBag = DisposeBag() //給成員變量賦值新的值
}
看一下下面運(yùn)行效果
用來(lái)給timer停止
下面例子timer開(kāi)始5秒后, 垃圾袋被賦值新的值,結(jié)束訂閱關(guān)系,timer停止,或者點(diǎn)擊按鈕立即停止timer
var disposeBag = DisposeBag()//成員變量垃圾袋
@IBAction func btnTimerStart(_ sender: Any) { //點(diǎn)擊按鈕開(kāi)始timer
var timer: Observable<Int>!
var i = 0
timer = Observable<Int>.interval(RxTimeInterval.seconds(1), scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print(num)
i += 1
if i > 5 { //5秒后, 垃圾袋被賦值新的值,結(jié)束訂閱關(guān)系,timer停止
self.disposeBag = DisposeBag()
}
})
.disposed(by: disposeBag)
}
點(diǎn)擊按鈕讓垃圾袋賦值新的值,從而解除timer的訂閱關(guān)系,達(dá)到停止timer的目的
@IBAction func btnTimerStop(_ sender: Any) {
disposeBag = DisposeBag()//注意,這里給成員變量disposeBag賦值了新的對(duì)象以后,指向了新的空間,原來(lái)的disposeBag對(duì)象地址被釋放,這樣原來(lái)綁定的timer和通知監(jiān)聽(tīng)都被釋放了,想要好使,需要重新添加通知,和重新啟動(dòng)timer
}