【Swift】RxSwiftのPlaygroundを読む③

RxSwiftのPlaygroundを読んでみるシリーズ今回は複数のObservableを一つにまとめる操作についてです。
([Combining_Operators](https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Combining_Operators.xcplaygroundpage/Contents.swift))

# Combination Operators
いくつかのObservableを束ねて一つのObservableにする処理です。
支流が合流して本流になる如く、です。

## startWith
subscribeした際、startWithで指定した値が先に流れる。
複数startWithをつける場合は、後に付け足したものから流れる。

```swift
let disposeBag = DisposeBag()
let startWith川 = Observable
    .of("🍑1", "🍑2", "🍑3")
    .startWith("🍑0-1", "🍑0-2")
    .startWith("🍑0-0")

startWith川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
```

**結果**

```
Next(🍑0-0)
Next(🍑0-1)
Next(🍑0-2)
Next(🍑1)
Next(🍑2)
Next(🍑3)
Completed
```

# merge
シンプルに複数のObservableを1つに束ねる。
それぞれの支流を流れてくる値を受け取ることができる。

```swift
let disposeBag = DisposeBag()

let 川1 = PublishSubject<String>()
let 川2 = PublishSubject<String>()
let merge川 = Observable
    .of(川1, 川2)
    .merge()

merge川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

川1.onNext("🍑1") // 1の川に値を流す
川2.onNext("🍑2") // 2の川に値を流す
```

**結果**

```
Next(🍑1)
Next(🍑2)
```

## zip
複数のObservableを束ね、
それぞれの支流を流れる値が揃ったときに初めて、
まとめた値が本流に流れる。

```swift
let disposeBag = DisposeBag()

let string川 = PublishSubject<String>()
let int川 = PublishSubject<Int>()
let zip川 = Observable
    .zip(string川, int川) { stringElement, intElement in
        return stringElement + ": \(intElement)"
    }

zip川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

string川.onNext("🍑")
string川.onNext("🍑🍑")

int川.onNext(0)
```

**結果**

```
Next(🍑: 0)
// ←int川の2つ目の値がまだ流れていないので、🍑🍑の値も流れてこない
```

## combineLatest
複数のObservableを束ね、
ある支流で値が流れてきたときに、
その他の支流で直前に流れた値を再び流して一つの値にする。
すべての支流で一度値が流れるまでは、本流に値が流れない。

```swift
let disposeBag = DisposeBag()

let string川 = PublishSubject<String>()
let int川 = PublishSubject<Int>()
let combineLatest川 = Observable
    .combineLatest(string川, int川) { stringElement, intElement in
        return stringElement + ": \(intElement)"
    }

combineLatest川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

string川.onNext("🍑")
string川.onNext("🍑🍑")

int川.onNext(0)
```

**結果**

```
Next(🍑🍑: 0) // ←string川の直前の値とint川の最初の値
```

支流を配列でまとめることもできる。
この場合、同じ型の値をもつObservableしか束ねることができない。

```swift
let disposeBag = DisposeBag()

let 川1 = PublishSubject<String>()
let 川2 = PublishSubject<String>()
let 川3 = PublishSubject<String>() // Intにはできない

let combineLatest川 = [川1, 川2, 川3]
    .combineLatest { $0[0] + $0[1] + $0[2] }

combineLatest川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

川1.onNext("🍑1-1")
川1.onNext("🍑1-2")

川2.onNext("🍑2")
川3.onNext("🍑3")
```

**結果**

```
Next(🍑1-2🍑2🍑3)
```

## switchLatest
複数のObservableを束ねるものの、
電車の切り替えポイントのように、支流を切り替えるObservableを作る。

```swift
let disposeBag = DisposeBag()

let 川1 = PublishSubject<String>()
let 川2 = PublishSubject<String>()

let variable川 = Variable(川1)

let switchLatest川 = variable川
    .asObservable()
    .switchLatest()

switchLatest川
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

川1.onNext("🍑")
川2.onNext("🍎") // ←流れない

variable川.value = 川2 // ←川の切り替え

川1.onNext("🍊") // ←流れない
川2.onNext("🍏")
```

**結果**

```
Next(🍑)
Next(🍏)
```

# おわりに
この辺り、まさに川といった感じです。

次回は流れる値を別の値に変換する操作です。

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