观察者(Observer)介绍
观察者(
Observer
)的作用就是监听事件,然后对这个事件做出响应。或者说任何响应事件的行为都是观察者
常见观察者
AnyObserver
- 任意一种观察者Binder
- 特定观察者:比如UI观察者
Observable 与 Observer 之间的关联
subscribe(...)
- 订阅bind(...)
- 绑定
AnyObserver
AnyObserver 可以用来描叙任意一种观察者
实例解析:
对于一个网络请求
let disposeBag = DisposeBag()
URLSession.shared.rx.data(request: URLRequest(url: url))
.subscribe(onNext: { data in
print("Data Task Success with count: \(data.count)")
}, onError: { error in
print("Data Task Error: \(error)")
})
.disposed(by: disposeBag)
如果拆分表示:
let disposeBag = DisposeBag()
let observer: AnyObserver<Data> = AnyObserver { (event) in
switch event {
case .next(let data):
print("Data Task Success with count: \(data.count)")
case .error(let error):
print("Data Task Error: \(error)")
default:
break
}
}
URLSession.shared.rx.data(request: URLRequest(url: URL(string: "www.baidu.com")!))
.subscribe(observer)
.disposed(by: disposeBag)
Binder
Binder 主要有以下两个特征:
- 不会处理错误事件
- 确保绑定都是在给定
Scheduler
上执行(默认MainScheduler
)
PS:
相较于 AnyObserver 的大而全,Binder 更专注于特定的场景, 典型的是成为 UI 观察者
一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息
实例解析:
通过 Binder 创建自定义的 UI 观察者
let disposeBag = DisposeBag()
let label = UILabel()
// 观察者
let observer: Binder<String> = Binder(label) { (view, text) in
// 收到发出的索引数后显示到label上
view.text = text
}
// 创建一个计时器(每1秒发送一个索引数)
let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer.map { "当前索引数:\($0)" }
.bind(to: observer)
.disposed(by: disposeBag)
Binder 在 RxCocoa 中的应用
其实 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
}
}
}