注意:使用本例中的代码首先应该导入头文件,代码如下:
import RxSwift
Working with Subjects
Subject 是一个桥梁或者代理,在 Rx 的某些实现里可见,它同时扮演了观察者和
Observable
的角色。因为它是一个观察者,所以它可以订阅一个或多个Observable
s,因为它又是一个Observable
,所以它可以回收它自己观察的 item,还可以发出新的 items。了解更多
Tips: 能力有限,上面的翻译的不是清楚。可以看看作者 yaqing 的 函数响应式编程框架RxSwift 学习——Subject 这篇文章,以便理解。
extension ObservableType {
/**
Add observer with `id` and print each emitted event.
- parameter id: an identifier for the subscription.
*/
func addObserver(_ id: String) -> Disposable {
return subscribe { print("Subscription:", id, "Event:", $0) }
}
}
func writeSequenceToConsole<O: ObservableType>(name: String, sequence: O) -> Disposable {
return sequence.subscribe { event in
print("Subscription: \(name), event: \(event)")
}
}
上面的这段代码只是辅助理解,方便测试。
PublishSubject
在所有的观察者订阅之后广播新的事件。意思是说,每个观察者只能观察到在自己订阅之后Observable
发出的事件。
example("PublishSubject") {
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("⚽️")
subject.onNext("🏀")
}
Debug Area 输出:
--- PublishSubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(⚽️)
Subscription: 2 Event: next(⚽️)
Subscription: 1 Event: next(🏀)
Subscription: 2 Event: next(🏀)
Tips: 这个例子还介绍了使用
onNext(_:)
便利方法,这个方法相当于on(.next(_:))
方法,这两个方法会导致一个提供element
的新事件被发散到订阅者们上。还有onError(_:)
和onCompleted()
便利方法,分别相当于on(.error(_:))
方法和on(.completed)
方法。
ReplaySubject
广播新事件到所有的订阅者们上,并且可以把 指定bufferSize
数量的在新订阅者订阅之前广播的事件发送到新订阅者上。
example("ReplaySubject") {
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("⚽️")
subject.onNext("🏀")
}
Debug Area 输出:
--- ReplaySubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(⚽️)
Subscription: 2 Event: next(⚽️)
Subscription: 1 Event: next(🏀)
Subscription: 2 Event: next(🏀)
BehaviorSubject
广播新的事件到所有的订阅者们上,并且首先发送最近的一个(或者默认的)值到订阅者们上,然后再发送订阅之后的事件。
example("BehaviorSubject") {
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("⚽️")
subject.onNext("🏀")
subject.addObserver("3").addDisposableTo(disposeBag)
subject.onNext("🍐")
subject.onNext("🍊")
}
Debug Area 输出:
--- BehaviorSubject example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(⚽️)
Subscription: 2 Event: next(⚽️)
Subscription: 1 Event: next(🏀)
Subscription: 2 Event: next(🏀)
Subscription: 3 Event: next(🏀)
Subscription: 1 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 2 Event: next(🍊)
Subscription: 3 Event: next(🍊)
注意到在前面这些例子中少了些什么吗?一个 Completed 事件。当
PublishSubject
,ReplaySubject
和BehaviorSubject
即将被处理的时候,它们不会自动发出 Completed 事件。
Variable
封装一个BehaviorSubject
,所以它将首先发送最近的一个(或者默认的)值到新的订阅者们然后再发送订阅之后的事件。并且Variable
还会维护当前值的状态。Variable
将不会发出 Error 事件。然而,它将会自动地发出一个 Completed 事件并且终止于 deinit
。
example("Variable") {
let disposeBag = DisposeBag()
let variable = Variable("🔴")
variable.asObservable().addObserver("1").addDisposableTo(disposeBag)
variable.value = "🐶"
variable.value = "🐱"
variable.asObservable().addObserver("2").addDisposableTo(disposeBag)
variable.value = "⚽️"
variable.value = "🏀"
}
Debug Area 输出:
--- Variable example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(⚽️)
Subscription: 2 Event: next(⚽️)
Subscription: 1 Event: next(🏀)
Subscription: 2 Event: next(🏀)
Subscription: 1 Event: completed
Subscription: 2 Event: completed
调用
Variable
实例的asObservable()
方法是为了访问BehaviorSubject
序列的底层。Variable
不会实现on
操作(或者 onNext(_:)),而是暴露一个可以获取当前值的属性。设置一个新值还会添加这个值到它的底层BehaviorSubject
序列。