RxSwiftについてようやく理解できてきたのでまとめることにした(3)


# Observableの変換基礎　〜filter, map, flatMap〜

3つめの記事です。ここからが本番という感じです！
[1つめの記事](http://qiita.com/_ha1f/items/e16ddc6017c4ad807c3c)
[2つめの記事](http://qiita.com/_ha1f/items/43b28792d27dbee7133d)

イベントを発生させるObservableですが、これらは変換・合成などができます。この章では基本的な3つの変換、

- map
- filter
- flatMap

について書きます。

# filter

```swift
let observable: Observable<Int> = Observable.from([1,2,3,4,5])
let filteredObservable: Observable<Int> = observable
    .filter { value in value > 3 }
```

元のObservableを、onNextで渡された値について、条件がtrueの要素のみからなるObservableに変換します。onCompletedやonErrorはそのまま流します。

上の例の場合は、

> onNext(4) -> onNext(5) -> onCompleted()


# map

```swift
let observable: Observable<Int> = Observable.from([1,2,3,4,5])
let mappedObservable: Observable<Int> = observable
    .map { value in value * 2 }
```

mapはonNextで流れる値を変換します。onErrorやonCompletedなどはそのまま流します。

上の例の場合は、

> onNext(2) -> onNext(4) -> onNext(6) -> onNext(8) -> onNext(10) -> onCompleted()

中の実装によって、型が変わる場合もあります。

```swift
let observable: Observable<Int> = Observable.from([1,2,3,4,5])
let mappedObservable: Observable<String> = observable
    .map { value in "\(value)" }
```

この場合、元のobservableは`Observable<Int>`ですが、`map`により`Observable<String>`に変換されています。

# flatMap

flatMapは一番良く使うOperatorで、RxSwiftによる処理の醍醐味のようなものです！
Promiseみたいな感じで、非同期の処理をどんどんつなげることができます。

値で説明するなら、以下のような感じです。

```swift
let observable: Observable<Int> = Observable.from([1,2,3,4,5])
let flatMappedObservable: Observable<Int> = observable
    .flatMap { value in Observable.from(0..<value) }
```

この例だと、onNextで

> 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4

のあとにonCompletedが流れてきます。

区切るとわかりやすいと思いますが、それぞれの値に対してのObservableから流れる値が、連結されています。
（本当は並列処理などにより、順番が入れ替わる可能性があります）

flatMapでも、observableの型が変わる可能性があります。

## 中身のイベント

もちろん、中身のObservableの放つonNextは外側のobservableに流れます。
中身のObservableの放つonErrorも外側にも流れます。

よって、もし中身が一つでも失敗した場合は全体のsubscriptionが終了してしまいます。

これをしたくない場合は、以下のように中身のerrorを無視する必要があります。

```swift
// errorのときにデフォルト値を返す
.flatMap { value -> Observable<Int> in
    return Observable<Int>.error(NSError())
        .catchErrorJustReturn(1)
}

// errorのときに無視する
.flatMap { value -> Observable<Int> in
    return Observable<Int>.error(NSError())
        .catchError { error in
            return error
                .flatMap { _ inObservable<Int>.empty() }
        }
}
```

また、onCompletdは大元のonCompletedのみが使われて、
flatMap内のObservableのonCompletedは無視されます。

もし中身のonCompletedで全体のsubscriptionが終了してしまっては、
２つ目の要素が無視されてしまいます。

もし外側にも流したい場合は、少し工夫する必要があります。
（記事では書きませんが、`takeUntil`オペレータ などを使うと実現できます）

## flatMapの利用例

例えば、ボタンがタップされたらデータを取ってきてラベルに反映する、という処理は以下のように書きます。

```swift
self.button.rx.tap
    .flatMap { [weak self] event in self?.fetchData() }
    .subscribe(onNext: { [weak self] data in
        self?.label.text = data.title
    })
    .disposed(by: self.disposeBag)
```

※`fetchData()`はObservable<FooData>を返します。

リクエストが複数段必要な場合も、どんどん繋げられるのがわかるかと思います！
（flatMapの後ろにまたflatMapをつなぐ）
こうすると、コールバック地獄のようにインデントが重ならないですね！

```swift
self.button.rx.tap
    .flatMap { [weak self] event in self?.fetchData() }
    .flatMap { [weak self] data in self?.fetchUser(data.userId) }
    .subscribe(onNext: { [weak self] user in
        self?.label.text = data2.title
    })
    .disposed(by: self.disposeBag)
```

ちなみに、以下のように書いても同じですが、インデント的に見にくいので、上のように書いたほうが良いです。
（ただし、エラーとかの扱いがちょっと変わるので、必要なときはあえて下のようにネストさせて書く場合もあります。）

```swift
self.button.rx.tap
    .flatMap { [weak self] event in 
        self?.fetchData()
            .flatMap { [weak self] data in self?.fetchUser(data.userId) }
    }
    .subscribe(onNext: { [weak self] user in
        self?.label.text = data2.title
    })
    .disposed(by: self.disposeBag)
```

# オペレータ

こういうObservableを変換するもののことをオペレータと呼びます。
（ここまでで説明したのは`filter`, `map`, `flatMap`）

以下のように、オペレータによってObservableは変換されていきます。変換の途中でもObservableです。（Elementの型は変わることもあります）
※実際はそれぞれは新しいObservableです。

```swift
let barObservable = fooObservable
    .hogeオペレータ  // この時点でもobservable
    .fugaオペレータ  // この時点でもobservable
    .piyoオペレータ  // この時点でもobservable
```


上に上げたのは最も基礎的なオペレータで、他にも多くのオペレータがあります。
上でちらっと紹介した `catchErrorJustReturn`, `catchError`, `takeUntil`もオペレータの一つです。
他にも、`take`, `merge`, `withLatestFrom`, `amb` など様々なオペレータがあり、
必要に応じて使い分けるとより良くかけます！

が、とりあえずこの３つが使えれば基礎はOKかなと思います！
時間があればそれらについても説明したいと思います！

続き→https://qiita.com/_ha1f/items/2d0fc50505ce3a1fcdab