RxSwift Observer-观察者

我们在之前已经了解了什么是Observer观察者,这篇我们了解一下怎么创建观察者以及特征观察者(AnyObserverBinder)。

在 subscribe 方法中创建

创建观察者最直接的方法就是在Observablesubscribe方法后面描述当事件发生时,需要如何做出响应。举个🌰:

1
2
3
4
5
6
7
8
let observable = Observable.of(1,2,3,4,5)
observable.subscribe(onNext: { element in
print(element)
}, onError: { error in
print(error)
}, onCompleted: {
print("completed")
})

运行结果如下:
运行结果.png

在bind方法中创建

我们创建一个定时生成索引数的Observable序列,并将索引数不断显示在label标签上
举个🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import UIKit
import RxCocoa
import RxSwift

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable.map{ "当前索引数:\($0)" }
.bind { [weak self](text) in
self?.label.text = text
}.disposed(by: disposeBag)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

运行结果:
bind结果.png
除了以上创建方法外,我们还可以使用其他的方式,比如AnyObserverBinder

使用AnyObserver创建观察者

AnyObserver可以用来描叙任意一种观察者

配合subscribe方法使用
1
2
3
4
5
6
7
8
9
10
11
12
let observer: AnyObserver<Int> = AnyObserver { event in
switch event{
case .next(let data):
print(data)
case .error(let error):
print(error)
case .completed:
print("completed")
}
}
let observable = Observable.of(1,2,3,4,5)
observable.subscribe(observer)

运行结果如下:
运行结果.png

配合bindTo方法使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import UIKit
import RxCocoa
import RxSwift

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let observer: AnyObserver<String> = AnyObserver{
[weak self] event in
switch event{
case .next(let text):
self?.label.text = text
default:
break
}
}
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable.map{"当前索引数:\($0)"}
.bind(to: observer)
.disposed(by: disposeBag )
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Binder

Binder 主要有以下两个特征:

  • 不会处理错误事件
  • 确保绑定都是在给定Schedule上执行(默认MainScheduler

一旦产生错误事件,在调试环境下将执行fatalError,在发布环境下将打印错误信息
在上面更新label文字的例子中,更好的方式就是使用Binder。理由有二:

  • UI的更新在主线程完成
  • 只处理next事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import UIKit
    import RxCocoa
    import RxSwift

    class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    let disposeBag = DisposeBag()
    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let observer: Binder<String> = Binder(label){
    (view,text) in
    view.text = text
    }
    let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
    observable.map{ "当前索引数:\($0)"}
    .bind(to: observer)
    .disposed(by: disposeBag)
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    }
    }

下面,我们再去实现另外一段代码:

1
2
3
4
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable.map{ $0 % 2 == 0}
.bind(to: label.rx.isHidden)
.disposed(by: disposeBag)

此时label会不断的消失、出现。这段代码里我们又操作了什么?查看label.rx.isHiddenisHidden可以发现

1
2
3
4
5
6
7
extension Reactive where Base: UIView {
public var isHidden: Binder<Bool> {
return Binder(self.base) { view, hidden in
view.isHidden = hidden
}
}
}

其实RxCocoa在对许多 UI 控件进行扩展时,就利用Binder将控件属性变成观查者,我们也可以用这种方式来创建自定义的 UI 观察者。