Help us understand the problem. What is going on with this article?

【Swift】RxSwiftのPlaygroundを読む②

More than 1 year has passed since last update.

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を束ねる処理についてです。

参考

https://github.com/ReactiveX/RxSwift/tree/master/Rx.playground

KentaKudo
イギリスの会社でソフトウェアエンジニアをしています。
https://kentakudo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away