简介
观察者 (Observer
) 的作用就是监听事件,然后对这个事件做出响应,或者说任何响应事件的行为都是观察者。比如:
- 当前视频播放到30分钟时,弹出视频小剧场(广告),后者就是
观察者
。 - 当前温度高于30度,打开空调降温,后者就是
观察者
。 - 当你点击视频拍摄时,系统弹出弹框问你是否同意使用摄像头,后者就是
观察者
。 - ······
eg:
tap.subscribe(onNext: { [weak self] in
self?.showAlert()
}, onError: { error in
print("发生错误: \(error.localizedDescription)")
}, onCompleted: {
print("任务完成")
})
在这里,弹出提示框就是 观察者
。
创建观察者最直接的方法就是在 Observable
的 subscribe
方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNext
,onError
,onCompleted
的这些闭包构建出来的。此外,我们还有AnyObserver
、Binder
方式创建观察者。
AnyObserver
AnyObserver 可以用来描叙任意一种 观察者
。
eg:
- 打印网络请求结果
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 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))
.subscribe(observer)
.disposed(by: disposeBag)
- 打印网络请求结果
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
可以看作是:
let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
switch event {
case .next(let isHidden):
self?.usernameValidOutlet.isHidden = isHidden
default:
break
}
}
usernameValid
.bind(to: observer)
.disposed(by: disposeBag)
Binder
基本介绍
1、相较于 AnyObserver
的大而全,Binder
更专注于特定的场景。Binder
主要有以下两个特征:
- 不会处理错误事件
- 确保绑定都是在给定
Scheduler
上执行(默认MainScheduler
)
2、一旦产生错误事件,在调试环境下将执行 fatalError
,在发布环境下将打印错误信息。
eg:
import RxSwift
import RxCocoa
@IBOutlet weak var lable: UILabel!
func test() {
let disposeBag = DisposeBag()
// 观察者
let observer: AnyObserver<String> = AnyObserver { [weak self] (event) in
switch event {
case .next(let text):
// 收到发出的索引数后显示到label上
self?.lable.text = text
default:
break
}
}
// Observable序列(just:创建一个序列,只包含一个元素)
let observable = Observable<Int>.just(100)
observable.map { (index) -> String in
return "当前索引数:\(index)"
}.observeOn(MainScheduler.instance).bind(to: observer).disposed(by: disposeBag)
}
在上面示例代码中,label
标签的文字显示就是一个典型的 UI
观察者。它在响应事件时,只会处理 next
事件,而且更新 UI
的操作需要在主线程上执行。那么这种情况下更好的方案就是使用 Binder
,代码如下:
import RxSwift
import RxCocoa
@IBOutlet weak var lable: UILabel!
func test() {
let disposeBag = DisposeBag()
// 观察者
let observer: Binder<String> = Binder(lable) { (view, text) in
// 收到发出的索引数后显示到label上
view.text = text
}
// Observable序列(just:创建一个序列,只包含一个元素)
let observable = Observable<Int>.just(100)
observable.map { (index) -> String in
return "当前索引数:\(index)"
}.observeOn(MainScheduler.instance).bind(to: observer).disposed(by: disposeBag)
}
附:Binder
在 RxCocoa
中的应用
1、其实 RxCocoa
在对许多 UI
控件进行扩展时,就利用 Binder
将控件属性变成观查者,比如 UIControl+Rx.swift
中的 isEnabled
属性便是一个 observer
:
import RxSwift
import UIKit
extension Reactive where Base: UIControl {
// Bindable sink for `enabled` property.
public var isEnabled: Binder<Bool> {
return Binder(self.base) { control, value in
control.isEnabled = value
}
}
}
2、因此我们可以将序列直接绑定到它上面。比如下面样例,就可以用来判断 button
可用
/ 不可用
。
@IBOutlet weak var button: UIButton!
@IBAction func buttonClick(_ sender: UIButton) {
print("点击了按钮")
}
func test() {
let disposeBag = DisposeBag()
let observable = Observable<Int>.just(100)
observable.map { (e) -> Bool in
return (e != 100)
}.observeOn(MainScheduler.instance).bind(to: button.rx.isEnabled).disposed(by: disposeBag)
}
Author
如果你有什么建议,可以关注我的公众号:iOS开发者进阶
,直接留言,留言必回。
![](https://img.haomeiwen.com/i3096256/302e6ffbd82f3870.png)
网友评论