【Swift】RxSwiftのPlaygroundを読む②

RxSwiftのPlaygroundを読んでみるシリーズ今回はSubjectについてです。
([Working_with_Subjects](https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Working_with_Subjects.xcplaygroundpage/Contents.swift))

# Subject
Subjectも川です。
[RxSwiftのPlaygroundを読む①](http://qiita.com/KentaKudo/items/d9ff7cdc639c24301456#observable)で説明した内容と同じことが言えます。

Subjectは加えて、
eventを好きなタイミングで流すことができます。
(subscribeされていなくても。)

複数のsubscribeを区別するため、subscribeメソッドが定義されている
ObservableTypeに以下のメソッドを生やしておきます。

```swift
extension ObservableType {
    
    func subscribe(withID id: String) -> Disposable {
        return subscribe { print("Subscription:", id, "Event:", $0) }
    }
}
```

## PublishSubject
最もシンプルなSubject。
eventを送ったタイミングでsubscribeしていれば、
eventを受け取ることができるSubject。
(過去に送ったeventは受け取れない。)
また、deinit時にcompleteを流さない。

```swift
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")
```

**結果**

```swift
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を流さない。

```swift
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を流さない。

```swift
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が流れる。

```swift
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