この記事は、俺的RxSwiftまとめ①,俺的RxSwiftまとめ②,俺的RxSwiftまとめ③(Observableとは何か? - その1),俺的RxSwiftまとめ④(disposebagとは?)の続きです。
#Subjectとは何か?
Subject
はobserver
としてもobservable
としても動作するもの。
イベントの受け取って処理/イベントを発生させることができるものである。。
##PublishSubject
PublishSubject
は、初期値無しの状態でスタートし、subscriber
にはsubscribe
してから新しく放出された要素のみを伝えるSubject
である。(ただし、completed
/error
は放出された後にsubscribe
したsubscriber
にも伝達される。)
マーブルダイアグラムに示すと、
となる
また、マーブルダイアグラムをコードで表現すると、
let publishSubject = PublishSubject<String>()
publishSubject.onNext("1")
let subscriber1 = publishSubject
.subscribe{ event in
print("subscriber1:" , event.element ?? event)
}
publishSubject.onNext("2")
let subscriber2 = publishSubject
.subscribe{ event in
print("subscriber2:" , event.element ?? event)
}
publishSubject.onNext("3")
publishSubject.onCompleted()
let subscriber3 = publishSubject
.subscribe{ event in
print("subscriber3:" , event.element ?? event)
}
subscriber1: 2
subscriber1: 3
subscriber2: 3
subscriber1: completed
subscriber2: completed
subscriber3: completed
となる。
###どんな時に使われるのか?
PublishSubject
は新しいイベントをsubscriber
に通知する時に便利なので、ユーザーのクリックに応じた更新などに用いられる。また、リアルタイム性に優れているので、頻繁にやり取りが行われるチャット等に応用が考えられる。
##BehaviorSubject
BehaviorSubject
はPublishSubject
にreplay
(=最新のイベントをsubscriber
に伝達すること)の概念を付け加えたもの。そのため、初期値がないとreplay
できずエラーとなります。初期値を持たせるか、element
をoptional
として定義することが必須となる。
マーブルダイアグラムに示すと、
となる。
また、マーブルダイアグラムをコードで表現すると、
let behaviorSubject = BehaviorSubject<String>(value: "1")
let subscriber1 = behaviorSubject
.subscribe{ event in
print("subscriber1:" , event.element ?? event)
}
behaviorSubject.onNext("2")
let subscriber2 = behaviorSubject
.subscribe{ event in
print("subscriber2:" , event.element ?? event)
}
behaviorSubject.onNext("3")
behaviorSubject.onCompleted()
let subscriber3 = behaviorSubject
.subscribe{ event in
print("subscriber3:" , event.element ?? event)
}
subscriber1: 1
subscriber1: 2
subscriber2: 2
subscriber1: 3
subscriber2: 3
subscriber1: completed
subscriber2: completed
subscriber3: completed
###どんな時に使われるのか?
BehaviorSubject
はビューにSubject
の最新の状態を表せるので、placeholder
に最新の値をあらかじめ入れておく、ロード中のインジケーターを示す等の場面で用いられる。
##ReplaySubject
BehaviorSubject
では、最新のイベントのみをsubscriber
に伝達できたが、ReplaySubject
はバッファサイズに指定した数だけイベントを伝達することができる。ただし、バッファサイズを大きくしたり、画像のようなデータサイズが大きいものを使いすぎると、メモリ逼迫の原因となるので注意が必要である。
マーブルダイアグラムに示すと、
となる
また、マーブルダイアグラムをコードで表現すると、
let replaySubject = ReplaySubject<String>.create(bufferSize: 2)
replaySubject.onNext("1")
replaySubject.onNext("2")
let subscriber1 = replaySubject
.subscribe { event in
print("subscriber1:", event.element ?? event)
}
replaySubject.onNext("3")
subscriber1: 1
subscriber1: 2
subscriber1: 3
となる。
###どんな時に使われるのか?
以前との差分を取りたい時などに使われる。
##AsyncSubject
AsyncSubject
は、completed
が流れた直後に、最後の値をsubscriber
に渡すもの。
マーブルダイアグラムに示すと、
となる。
これをコードで表すと、
let asyncSubject = AsyncSubject<String>()
asyncSubject.onNext("1")
let subscriber1 = asyncSubject
.subscribe { event in
print("subscriber1:", event.element ?? event)
}
asyncSubject.onNext("2")
let subscriber2 = asyncSubject
.subscribe { event in
print("subscriber2:", event.element ?? event)
}
asyncSubject.onNext("3")
asyncSubject.onCompleted()
subscriber1: 3
subscriber2: 3
subscriber1: completed
subscriber2: completed
となる。
###どんな時に使われるのか?
APIのコールバックを受ける時に便利
#Relayとは何か?
Relay
は、subjects
のラッパーのことである。ラッパーとして果たす役割は、error
やcompleted
を受け付けず、accept(_:)
でnext
で流れるelementのみを通すことである。
PublishRelay
はPublishSubject
,BehaviorRelay
はBehaviorSubject
に対応している。
コードに示すとそれぞれ、以下のようになる。
let publishRelay = PublishRelay<String>()
let disposeBag = DisposeBag()
publishRelay.accept("1")
publishRelay
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
publishRelay.accept("2")
2
let behaviorRelay = BehaviorRelay(value: "Initial value")
let disposeBag = DisposeBag()
behaviorRelay.accept("1")
behaviorRelay
.subscribe {
print("subscriber1:" , $0.element ?? $0)
}
.disposed(by: disposeBag)
behaviorRelay.accept("2")
behaviorRelay
.subscribe {
print("subscriber2:", $0.element ?? $0)
}
.disposed(by: disposeBag)
behaviorRelay.accept("3")
subscriber1: 1
subscriber1: 2
subscriber2: 2
subscriber1: 3
subscriber2: 3
となる。