Observer创建
观察者 是用来监听事件,然后它需要这个事件做出响应
常见观察者
- AnyObserver - 任意一种观察者
- Binder - 特定观察者:比如UI观察者
Observable 与 Observer 之间的关联
- subscribe(...) - 订阅
- bind(...) - 绑定
- 直接在subscribe中创建
直接在Observable的subscribe方面后面描述当事件发生时,如何作出响应
func subObserver() {
let ofSequence = Observable.of(1,2,3)
_ = ofSequence.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
})
}
运行结果:
1
2
3
completed
-
在bind方法中创建
func bindObserver() { let intervalSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance) _ = intervalSequence.bind { element in print(element) } }
运行结果:
0
1
2
3
...
3.使用 AnyObserver创建
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)
}
运行结果:
1
2
3
completed
- 使用Binder创建
Binder 主要有以下两个特征:
- 不会处理错误事件
- 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler)
相较于 AnyObserver 的大而全,Binder 更专注于特定的场景, 典型的是成为 UI 观察者
一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息
func binderObserver() {
let observer = Binder<String>(label) { (label,element) in
print(element)
label.text = element
}
let ofSequence = Observable.of(1,2,3)
_ = ofSequence.map{"当前值为:\($0)"}
.subscribe(observer)
}
运行结果:
当前值为:1
当前值为:2
当前值为:3
RXCocoa中对很多控件做了扩展,就是利用Binder将控件属性变为观察者。
- UI 控件在 RxCocoa 下某些属性都是被观察者(Observable),都可以发出序列,常见的有
- 控件的 text 类型是 ControlProperty<String> ,最终遵循 ObservableType协议
- 按钮的点击 tap 类型是 ControlEvent<Void>,最终遵循 ObservableType协议
- 对于设置 UI 控件的一些 Bool 类型的属性,如可输入,可点击,一般用 Binder (遵循 ObserverType协议) 来生成观察者,对接受的数据条件进行判断是否可以输入、可点击
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{"当前值为:\($0)"}
.bind(to: label.rx.text)
}
其实 RxCocoa 在对许多 UI 控件进行扩展时,就利用 Binder 将控件属性变成观查者
比如 UIControl+Rx.swift 中的 isEnabled 属性便是一个 observer :
UIControl+Rx
/// 按钮是否可点击 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 的当前文本 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
}
}
}
网友评论