observer(观察者)
观察者(Observer)
的作用就是监听事件,然后对这个事件做出响应。或者说任何响应事件的行为
都是观察者
观察者
的创建有以下几种
- 在
subscribe
和binder
的方法中创建观察者- 使用
AnyObserver
创建观察者- 使用
Binder
创建观察者
我们一般
在subscribe
、bind
方法中直接创建观察者
- 在
subscribe
中直接创建
- 创建观察者最直接的方法就是在
Observable
的subscribe
方法后面描述当事件发生时,需要如何做出响应。- 比如下面的样例,观察者就是由后面的
onNext,onError,onCompleted
这些闭包构建出来的
Observable<String>.of("Json","XML")
.subscribe { (element) in
print("---of---\(element)")
} onError: { (error) in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}
onNext,onError,onCompleted
这些就是不同的观察者
- 在
bind
中直接创建,主要用于绑定各种控件
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "当前索引数:\($0 )"}
.bind { [weak self](text) in
//收到发出的索引数后显示到label上
self?.label.text = text
}
.disposed(by: disposeBag)
这种方式
label
只能处理Next
的事件,而且刷新UI
只能在主线程
里面刷新
使用 AnyObserver 创建观察者
AnyObserver
可以用来描述任何一种观察者,我们可以配合subcribe
和bind(to)
使用
- 配合
subcribe
使用:
// 观察者
let observer: AnyObserver<String> = AnyObserver{event in
switch event {
case .next(let element):
print(element)
case .error(let error):
print("错误:\(error)")
case .completed:
print("completed")
}
}
// 创建观察序列
let observable = Observable.of("JSON","XML")
observable.subscribe(observer)
// JSON
// XML
// completed
- 配合
bind(to)
使用
//创建观察者
let observer: AnyObserver<String> = AnyObserver { (envnt) in
switch envnt {
case .next(let title):
// 把数据绑定到按钮上
self.TestButton.setTitle(title, for: .normal)
default:
break
}
}
// 序列
let observable = Observable.of("测试")
_ = observable.bind(to: observer)
使用 Binder 创建观察者
一般在特定
的场景下会使用binder
创建观察者
binder
有两大特征:
- 不会处理错误事件
- 确保绑定都是在给定
Scheduler
上执行(默认MainScheduler
)
//创建 binder 观察者
let binderObserver: Binder<String> = Binder(self.testTextField) { (view, value) in
view.text = value
}
// 序列
let observable = Observable.of("测试")
_ = observable.bind(to: binderObserver)
binder
一般结合控件使用,在RxCocoa
里面运用较多,如:
// 为 UIControl 添加一个扩展
extension Reactive where Base: UIControl {
public var isEnabled: Binder<Bool> {
return Binder(self.base) { control, value in
control.isEnabled = value
}
}
}
//Observable序列(每隔1秒钟发出一个索引数)
// 用 button.rx 把isEnabled 和事件关联起来
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { $0 % 2 == 0 }
.bind(to: button.rx.isEnabled)
.disposed(by: disposeBag)
Subjects 介绍
- 有时我们希望
Observable
在运行时能动态地“获得”或者说“产生”
出一个新的数据,再通过 Event 发送出去。这时候我们就可以用Subjects
来实现。比如
:订阅一个输入框的输入内容,当用户每输入一个字后,这个输入框关联的Observable
就会发出一个带有输入内容的Event
,通知给所有订阅者。
Subjects
即使订阅者
,又是观察者(observer)
因为
subjects
能够动态的接收新值,所以说他是订阅者
因为当subjects
有了新的值之后,就会通过Event
将新值发出给他的所有订阅者,所以说他是observer
Subjects
常用的方法有:
onNext(:)
:该方法相当于subject
接收到一个.next
事件。onError(:)
:该方法相当于subject
接收到一个.error
事件。onCompleted()
该方法相当于subject
接收到一个.completed
事件。
Subjects
有四种格式:PublishSubject
、BehaviorSubject
、ReplaySubject
、BehaviorRelay
相同点:
- 他们都是
Observable
,他们的订阅者都能收到他们发出的新的Event
- 在发出
..complete
或.error
事件以后,就会终结,就不再发出Event
事件了- 对于那些在
Subjects
终结后再订阅他的订阅者,也能收到subject
发出的一条.complete
或.error
的event
,告诉这个新的订阅者它已经终结了
不同点
- 当一个新的订阅者刚订阅它的时候,
能不能
收到Subject
以前发出过的旧Event
,如果能的话又能收到多少个。
PublishSubject
PublishSubject
是最普通的Subject
,它不需要初始值就能创建。PublishSubject
的订阅者从他们开始订阅的时间点起
,可以收到订阅后Subject
发出的新Event
,而不会收到他们在订阅前
已发出的Event
。
let publish = PublishSubject<String>()
publish.onNext("A") // A 在订阅之前赋值 不会被打印
publish.subscribe { (event) in
print(event.element)
}.disposed(by: disposeBag)
publish.onNext("B")
//print B
BehaviorSubject
BehaviorSubject
需要通过一个默认初始值
来创建。- 当一个订阅者来订阅它的时候,这个订阅者会立即收到
BehaviorSubjects 上一个
发出的event
。之后就跟正常的情况一样,它也会接收到BehaviorSubject
之后发出的新的event
// 需要初始值
let behavior = BehaviorSubject<String>(value: "A")
behavior.subscribe { (event) in
print(event.element)
}.disposed(by: disposeBag)
behavior.onNext("B")
//print A B
ReplaySubject
ReplaySubject
在创建时候需要设置一个bufferSize
,表示它对于它发送过的event
的缓存个数。- 比如一个
ReplaySubject
的bufferSize
设置为 2,它发出了 3 个.next
的event
,那么它会将后两个(最近的两个)
event
给缓存起来。此时如果有一个subscriber
订阅了这个ReplaySubject
,那么这个subscriber
就会立即收到前面缓存的两个.next
的event
。 - 如果一个
subscriber
订阅已经结束的ReplaySubject
,除了会收到缓存的.next
的event
外,还会收到那个终结的.error
或者.complete
的event
。
//创建一个bufferSize为2的ReplaySubject
let subject = ReplaySubject<String>.create(bufferSize: 2)
//连续发送3个next事件
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")
// 第1次订阅subject
// 打印最近两次的事件
subject.subscribe { event in
print("第1次订阅:", event)
}.disposed(by: disposeBag)
//第1次订阅: next(B)
//第1次订阅: next(C)
//再发送1个next事件
subject.onNext("D")
// 第1次订阅: next(B)
// 第1次订阅: next(C)
// 第1次订阅: next(D)
//
// //第2次订阅subject
// 打印缓存的最近两次的事件
subject.subscribe { event in
print("第2次订阅:", event)
}.disposed(by: disposeBag)
// 第1次订阅: next(B)
// 第1次订阅: next(C)
// 第1次订阅: next(D)
// 第2次订阅: next(C)
//第2次订阅: next(D)
//
//让subject结束
// 打印完成的事件
subject.onCompleted()
// 第1次订阅: next(B)
// 第1次订阅: next(C)
// 第1次订阅: next(D)
// 第2次订阅: next(C)
// 第2次订阅: next(D)
// 第1次订阅: completed
// 第2次订阅: completed
//第3次订阅subject
// 打印最近的两次缓存事件和完成事件
subject.subscribe { event in
print("第3次订阅:", event)
}.disposed(by: disposeBag)
// 第1次订阅: next(B)
// 第1次订阅: next(C)
// 第1次订阅: next(D)
// 第2次订阅: next(C)
// 第2次订阅: next(D)
// 第1次订阅: completed
// 第2次订阅: completed
// 第3次订阅: next(C)
// 第3次订阅: next(D)
// 第3次订阅: completed
BehaviorRelay
BehaviorRelay
是作为Variable
的替代者出现的。它的本质
其实也是对BehaviorSubject
的封装,所以它也必须要通过一个默认的初始值
进行创建。BehaviorRelay
具有BehaviorSubject
的功能,能够向它的订阅者发出上一个event
以及之后新创建的event
。- 与
BehaviorSubject
不同的是,不需要也不能手动给BehaviorReply
发送completed
或者error
事件来结束它(BehaviorRelay 会在销毁时也不会自动发送 .complete 的 event
)。 BehaviorRelay
有一个value
属性,我们通过这个属性可以获取最新值。而通过它的accept()
方法可以对值进行修改
//创建一个初始值为包含一个元素的数组的BehaviorRelay
let subject = BehaviorRelay<[String]>(value: ["1"])
//修改value值
subject.accept(subject.value + ["2"])
//第1次订阅
subject.asObservable().subscribe {
print("第1次订阅:", $0)
}.disposed(by: disposeBag)
//第1次订阅: next(["1", "2"])
//修改value值
subject.accept(subject.value + ["3"])
//第1次订阅: next(["1", "2", "3"])
//第2次订阅
subject.asObservable().subscribe {
print("第2次订阅:", $0)
}.disposed(by: disposeBag)
//第2次订阅: next(["1", "2", "3"])
//修改value值
subject.accept(subject.value + ["4"])
//第2次订阅: next(["1", "2", "3","4"])