Observer創(chuàng)建
觀察者 是用來監(jiān)聽事件,然后它需要這個(gè)事件做出響應(yīng)
常見觀察者
- AnyObserver - 任意一種觀察者
- Binder - 特定觀察者:比如UI觀察者
Observable 與 Observer 之間的關(guān)聯(lián)
- subscribe(...) - 訂閱
- bind(...) - 綁定
- 直接在subscribe中創(chuàng)建
直接在Observable的subscribe方面后面描述當(dāng)事件發(fā)生時(shí)意敛,如何作出響應(yīng)
func subObserver() {
let ofSequence = Observable.of(1,2,3)
_ = ofSequence.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
})
}
運(yùn)行結(jié)果:
1
2
3
completed
-
在bind方法中創(chuàng)建
func bindObserver() { let intervalSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance) _ = intervalSequence.bind { element in print(element) } }
運(yùn)行結(jié)果:
0
1
2
3
...
3.使用 AnyObserver創(chuàng)建
AnyObserver可以用來描述任意一種觀察者,可以配合subscribe和bindTo使用
func anyObserver() {
let observer = AnyObserver<Int> { event in
switch event {
case .next(let data):
print(data)
case .error(let error):
print(error)
case .completed:
print("completed")
}
}
let ofSequence = Observable.of(1,2,3)
// _ = ofSequence.subscribe(observer)
_ = ofSequence.bind(to: observer)
}
運(yùn)行結(jié)果:
1
2
3
completed
- 使用Binder創(chuàng)建
Binder 主要有以下兩個(gè)特征:
- 不會(huì)處理錯(cuò)誤事件
- 確保綁定都是在給定 Scheduler 上執(zhí)行(默認(rèn) MainScheduler)
相較于 AnyObserver 的大而全系冗,Binder 更專注于特定的場(chǎng)景, 典型的是成為 UI 觀察者
一旦產(chǎn)生錯(cuò)誤事件,在調(diào)試環(huán)境下將執(zhí)行 fatalError薪鹦,在發(fā)布環(huán)境下將打印錯(cuò)誤信息
func binderObserver() {
let observer = Binder<String>(label) { (label,element) in
print(element)
label.text = element
}
let ofSequence = Observable.of(1,2,3)
_ = ofSequence.map{"當(dāng)前值為:\($0)"}
.subscribe(observer)
}
運(yùn)行結(jié)果:
當(dāng)前值為:1
當(dāng)前值為:2
當(dāng)前值為:3
RXCocoa中對(duì)很多控件做了擴(kuò)展,就是利用Binder將控件屬性變?yōu)橛^察者惯豆。
- UI 控件在 RxCocoa 下某些屬性都是被觀察者(Observable)池磁,都可以發(fā)出序列,常見的有
- 控件的 text 類型是 ControlProperty<String> 楷兽,最終遵循 ObservableType協(xié)議
- 按鈕的點(diǎn)擊 tap 類型是 ControlEvent<Void>地熄,最終遵循 ObservableType協(xié)議
- 對(duì)于設(shè)置 UI 控件的一些 Bool 類型的屬性,如可輸入芯杀,可點(diǎn)擊端考,一般用 Binder (遵循 ObserverType協(xié)議) 來生成觀察者雅潭,對(duì)接受的數(shù)據(jù)條件進(jìn)行判斷是否可以輸入、可點(diǎn)擊
extension Reactive where Base: UILabel {
/// Bindable sink for `text` property.
public var text: Binder<String?> {
return Binder(self.base) { label, text in
label.text = text
}
}
/// Bindable sink for `attributedText` property.
public var attributedText: Binder<NSAttributedString?> {
return Binder(self.base) { label, text in
label.attributedText = text
}
}
}
直接使用
func rxObserver() {
let justSequence = Observable.just(1)
_ = justSequence.map{"當(dāng)前值為:\($0)"}
.bind(to: label.rx.text)
}
其實(shí) RxCocoa 在對(duì)許多 UI 控件進(jìn)行擴(kuò)展時(shí)却特,就利用 Binder 將控件屬性變成觀查者
比如 UIControl+Rx.swift 中的 isEnabled 屬性便是一個(gè) observer :
UIControl+Rx
/// 按鈕是否可點(diǎn)擊 button.rx.isEnabled:
extension Reactive where Base: UIControl {
public var isEnabled: Binder<Bool> {
return Binder(self.base) { control, value in
control.isEnabled = value
}
}
}
UILabel+Rx
/// label 的當(dāng)前文本 label.rx.text
extension Reactive where Base: UILabel {
public var text: Binder<String?> {
return Binder(self.base) { label, text in
label.text = text
}
}
}
UIView+Rx
extension Reactive where Base: UIView {
public var isHidden: Binder<Bool> {
return Binder(self.base) { (view, hidden) in
view.isHidden = hidden
}
}
}