RxSwiftのPlaygroundを読んでみるシリーズ今回はSubjectについてです。
(Working_with_Subjects)
Subject
Subjectも川です。
RxSwiftのPlaygroundを読む①で説明した内容と同じことが言えます。
Subjectは加えて、
eventを好きなタイミングで流すことができます。
(subscribeされていなくても。)
複数のsubscribeを区別するため、subscribeメソッドが定義されている
ObservableTypeに以下のメソッドを生やしておきます。
extension ObservableType {
func subscribe(withID id: String) -> Disposable {
return subscribe { print("Subscription:", id, "Event:", $0) }
}
}
PublishSubject
最もシンプルなSubject。
eventを送ったタイミングでsubscribeしていれば、
eventを受け取ることができるSubject。
(過去に送ったeventは受け取れない。)
また、deinit時にcompleteを流さない。
let disposeBag = DisposeBag()
let publishSubject川 = PublishSubject<String>()
publishSubject川
.subscribe(withID: "1")
.addDisposableTo(disposeBag)
publishSubject川
.onNext("🍑1")
publishSubject川
.onNext("🍑2")
publishSubject川
.subscribe(withID: "2")
.addDisposableTo(disposeBag)
publishSubject川
.onNext("🍑3")
publishSubject川
.onNext("🍑4")
結果
Subscription: 1 Event: Next(🍑1) // ←まだ2はsubscribeしていない
Subscription: 1 Event: Next(🍑2) // 同上
Subscription: 1 Event: Next(🍑3)
Subscription: 2 Event: Next(🍑3)
Subscription: 1 Event: Next(🍑4)
Subscription: 2 Event: Next(🍑4)
ReplaySubject
subscribe時に指定したbufferSize分の過去のeventを受け取れるSubject。
また、deinit時にcompleteを流さない。
let disposeBag = DisposeBag()
let replaySubject川 = ReplaySubject<String>.create(bufferSize: 1)
replaySubject川
.subscribe(withID: "1")
.addDisposableTo(disposeBag)
replaySubject川
.onNext("🍑1")
replaySubject川
.onNext("🍑2")
replaySubject川
.subscribe(withID: "2")
.addDisposableTo(disposeBag)
replaySubject川
.onNext("🍑3")
replaySubject川
.onNext("🍑4")
結果
Subscription: 1 Event: Next(🍑1)
Subscription: 1 Event: Next(🍑2)
Subscription: 2 Event: Next(🍑2) // ←1つ過去のeventを受け取っている
Subscription: 1 Event: Next(🍑3)
Subscription: 2 Event: Next(🍑3)
Subscription: 1 Event: Next(🍑4)
Subscription: 2 Event: Next(🍑4)
BehaviorSubject
subscribe時に、一つ過去のevent(最初にsubscribeする場合は初期値)を受け取れるSubject。
ReplaySubjectでbufferSizeを1にしたときと同様の挙動(初期値を除いて)。
また、deinit時にcompleteを流さない。
let disposeBag = DisposeBag()
let behaviorSubject川 = BehaviorSubject<String>(value: "🍑0")
behaviorSubject川
.subscribe(withID: "1")
.addDisposableTo(disposeBag)
behaviorSubject川
.onNext("🍑1")
behaviorSubject川
.onNext("🍑2")
behaviorSubject川
.subscribe(withID: "2")
.addDisposableTo(disposeBag)
behaviorSubject川
.onNext("🍑3")
behaviorSubject川
.onNext("🍑4")
結果
Subscription: 1 Event: Next(🍑0) // ←初期値
Subscription: 1 Event: Next(🍑1)
Subscription: 1 Event: Next(🍑2)
Subscription: 2 Event: Next(🍑2) // ←1つ過去のeventを受け取っている
Subscription: 1 Event: Next(🍑3)
Subscription: 2 Event: Next(🍑3)
Subscription: 1 Event: Next(🍑4)
Subscription: 2 Event: Next(🍑4)
Variable
BehaviorSubject同様、1つ過去のeventを受け取れるSubject。
相違点は
・valueプロパティに直近のnextの値が保存されており、新たにnextイベントを流す場合はvalueプロパティを変更する。
・errorが流れない。
・deinit時にcompleteが流れる。
let disposeBag = DisposeBag()
let variable川 = Variable("🍑0")
variable川.asObservable()
.subscribe(withID: "1")
.addDisposableTo(disposeBag)
variable川.value = "🍑1"
variable川.value = "🍑2"
variable川.asObservable()
.subscribe(withID: "2")
.addDisposableTo(disposeBag)
variable川.value = "🍑3"
variable川.value = "🍑4"
結果
Subscription: 1 Event: Next(🍑0)
Subscription: 1 Event: Next(🍑1)
Subscription: 1 Event: Next(🍑2)
Subscription: 2 Event: Next(🍑2)
Subscription: 1 Event: Next(🍑3)
Subscription: 2 Event: Next(🍑3)
Subscription: 1 Event: Next(🍑4)
Subscription: 2 Event: Next(🍑4)
おわりに
うまく言語化できないあたり、まだまだよくわかっていないようです。
些細なことでもいいので、何かありましたらコメントお願いします。
次回はいくつかのObservableを束ねる処理についてです。