よく使うRxSwiftのオペレーターをまとめてみた

# はじめに
どうも@kaneko77です。
今回はめちゃくちゃ多いRxSwiftの`オペレーター`で普段よく使っている物を共有します。
`RxSwift`については[こちら](https://qiita.com/_ha1f/items/e16ddc6017c4ad807c3c)が参考になります。
この記事では参考にしたサイトや説明を織り交ぜて共有していけたらなと思います。
それでは行ってみましょう〜

## こんな方対象
- RxSwiftってめちゃくちゃオペレーターあるけど何にどう使うかわからない..と思っている人

## 環境
[RxSwift 6.2.0](https://github.com/ReactiveX/RxSwift/tree/main/RxSwift)

# 私のよく使う`オペレーター`達

## デバック: `debug`
### 説明
- デバックしたい時に使う
- ストリームの流れを見たい時に使う

### コード
```swift
Driver.just("ストリーム流れを見ていこう！")
    .debug("ストリーム監視:")
    .drive()
    .disposed(by: disposeBeg)
```
### ログ
```
2021-06-16 17:47:59.571: ストリーム監視: -> subscribed
2021-06-16 17:47:59.572: ストリーム監視: -> Event next(ストリーム流れを見ていこう！)
2021-06-16 17:47:59.572: ストリーム監視: -> Event completed
2021-06-16 17:47:59.572: ストリーム監視: -> isDisposed
```


## ストリームの結合 : `merge`
### 参考
https://qiita.com/yum_fishing/items/5598d7d343f87e682dd0
### 説明
- 複数の`Observable `をまとめて使いたい時に使う。
- 関係なく早く処理が早く終わった順にストリームにイベントが流れます。

### コード
```swift
Driver.merge(
    .just(true), .just(false)
)
.drive{
    print("イベント発火!!! -> \($0)")
}.disposed(by: disposeBeg)
```
### ログ
```
イベント発火!!! -> true
イベント発火!!! -> false
```

## 指定期間内のイベント無視 : `Debounce `
### 参考
https://qiita.com/dekatotoro/items/be22a241335382ecc16e
### 説明
- APIを過剰に呼び出したりしたくない時に使う。
- 指定したインターバルに従ってフィルターする
- 指定したインターバルの時間経過しないとイベント流れない〜
- 遅延処理とかに活用できる。


### コード
ボタンを押してから2秒後にイベントが流れます。

```swift
// MARK: - ログ確認用
self.mainView.login.rx.tap
    .asDriver()
    .drive{ _ in
        print("ボタンを押した瞬間の時間:\(Date())")
    }
    .disposed(by: disposeBeg)

// MARK: - debounce確認用
self.mainView.login.rx.tap
    .asDriver()
    .debounce(.seconds(2))
    .drive{ _ in
        print("2秒後にボタン押したよ!!!")
        print("ここに入った時間:\(Date())")
    }
    .disposed(by: disposeBeg)
```
### ログ
```
ボタンを押した瞬間の時間:2021-06-16 06:47:54 +0000
2秒後にボタン押したよ!!!
ここに入った時間:2021-06-16 06:47:56 +0000
```

## 指定期間の間連続したイベントを無視 : `Debounce `
### 参考
https://qiita.com/dekatotoro/items/be22a241335382ecc16e
### 説明
- よくボタンの連続ボタン抑制に使われるオペレーター
- 指定した期間内に連続したイベントがあった場合、最初のイベントだけ流す。


### コード

```swift
// MARK: - ログ確認用
self.mainView.login.rx.tap
    .asDriver()
    .drive{ _ in
        print("ボタンを押した瞬間の時間:\(Date())")
    }
    .disposed(by: disposeBeg)

// MARK: - throttle確認用
self.mainView.login.rx.tap
    .asDriver()
    .throttle(.seconds(2), latest: false)
    .drive{ _ in
        print("2秒後にボタン押したよ!!!")
        print("ここに入った時間:\(Date())")
    }
    .disposed(by: disposeBeg)
```
### ログ
```
ボタンを押した瞬間の時間:2021-06-16 06:59:07 +0000
2秒後にボタン押したよ!!!
ここに入った時間:2021-06-16 06:59:07 +0000
ボタンを押した瞬間の時間:2021-06-16 06:59:07 +0000
ボタンを押した瞬間の時間:2021-06-16 06:59:08 +0000
ボタンを押した瞬間の時間:2021-06-16 06:59:08 +0000
```

## イベントを流すか条件定義する : `filter`
### 参考
https://qiita.com/_ha1f/items/db72471d0c9e82fab13d
### 説明
- 期待する値かどうか判別できてできなかったらイベントを流さない

### コード
```swift
// MARK: - filterでtrueのみ発火するように制御する
Driver.just(true)
    .filter{
        $0
    }
    .drive{ _ in
        print("通ったぞ〜〜〜1")
    }
    .disposed(by: disposeBeg)

// MARK: - falseの場合
Driver.just(false)
    .filter{
        $0
    }
    .drive{ _ in
        print("通ったぞ〜〜〜2")
    }
    .disposed(by: disposeBeg)
```
### ログ
```
通ったぞ〜〜〜1
```

## 値の変換 : `map`
### 参考
https://qiita.com/_ha1f/items/db72471d0c9e82fab13d
### 説明
- 流れてきた値の変換をしたい時に使う

### コード
```swift
Driver.just(Date())
    .debug("監視")
    .map {
        // 日付を１加算する
        return Calendar.current.date(byAdding: .day, value: 1, to: $0)!
    }
    .drive{
        print("😀:\($0)")
    }
    .disposed(by: disposeBeg)
```
### ログ
```
2021-06-16 17:47:59.572: 監視 -> subscribed
2021-06-16 17:47:59.573: 監視 -> Event next(2021-06-16 08:47:59 +0000)
😀:2021-06-17 08:47:59 +0000
2021-06-16 17:47:59.574: 監視 -> Event completed
2021-06-16 17:47:59.574: 監視 -> isDisposed
```

## 値を違う型に変更 : `flatMapLatest`
### 参考
https://qiita.com/akihisasen/items/96fb48050d94393962a2
### 説明
- Observable に変換してObservableしか通知しない。
- 次のイベントが流れると前のイベントが処理中でも構わず流れる。
- 常に最新のイベントを処理する。
- UITextFiledからの入力チェックなどに使える。
- 他にも`flatMapFirst `っていう兄弟がいる。（姉妹かもしれない）
### コード

```swift
Observable.just(Date())
    .flatMapLatest {
        Observable.just(Calendar.current.date(byAdding: .day, value: 1, to: $0)!)
    }
    .subscribe(onNext: {
        print("日付取得", $0)
    })
    .disposed(by: disposeBeg)
```

### ログ
```
日付取得 2021-06-17 11:36:23 +0000
```

## Observable生成 : `create`
### 参考
https://qiita.com/_ha1f/items/43b28792d27dbee7133d#create
### 説明
- 任意の処理をオペレーターの中で行いたい時に使う

### コード
```swift
Observable<Date?>.of( Date(), nil )
    .flatMapLatest { day in
        return Observable.create { observable in
            guard let day = day else {
                observable.onError(TestError.err)
                return Disposables.create()
            }
            let f = DateFormatter()
            f.dateStyle = .long
            f.timeStyle = .none
            f.timeZone = .current
            observable.onNext(f.string(from: day))
            observable.onCompleted()
            return Disposables.create()
        }
    }
    .subscribe{
        print("日付取得", $0)
    }
    .disposed(by: disposeBeg)
```
### ログ
```
日付取得 June 16, 2021
Unhandled error happened: err
```

## 指定した値の数だけイベントをスキップする : `skip `
### 説明
- 指定した値の数だけイベントのスキップをします
- 初回だけストリーム流したくない時などに使います。

### コード
```swift
Observable.of(1,2,3)
    .skip(1)
    .subscribe{
        print("取得:", $0)
    }
    .disposed(by: disposeBeg)

```
### ログ
```
取得: next(2)
取得: next(3)
取得: completed
```

## `[weak self]` を定義しなくて良い : `withUnretained `
### 参考
https://tech.connehito.com/entry/rxswift6
### 説明
- OptionalBindingが不要になる。

### コード
```swift
Observable.just("テストだよ！")
    .withUnretained(self)
    .subscribe(onNext: { owner, element in
        owner.mainView.testText.text = element
    })
    .disposed(by: disposeBeg)
```

## 値を組み合わせてストリームに流す : `withLatestFrom `
### 参考
https://qiita.com/k5n/items/17f845a75cce6b737d1e#withlatestfrom
### 説明
- 監視対象にストリームが流れた時欲しい値も一緒に流してくれる。
- TableViewのセルのタップの時に私は使ってた

### コード
```swift
let test1 = Driver.just("huga")

Driver.just("hoge")
    .debug("流れ")
    .withLatestFrom(test1){ hoge, huga in
        return (hoge, huga)
    }
    .drive{
        print("😍取得:", $0)
    }
    .disposed(by: disposeBeg)

```
### ログ
```
2021-06-16 21:28:53.676: 流れ -> subscribed
2021-06-16 21:28:53.677: 流れ -> Event next(hoge)
😍取得: ("hoge", "huga")
2021-06-16 21:28:53.678: 流れ -> Event completed
2021-06-16 21:28:53.678: 流れ -> isDisposed
```

## タイマー処理をする : `interval `
### 参考
https://dev.classmethod.jp/articles/ios-periodic-processing-with-rxswift-interval/
### 説明
- 一定間隔の値で処理をしたいとき。
- タイマー処理をしたい時に使う
### コード

```swift
Driver<Int>.interval(.seconds(2))
    .drive{ _ in
        print("2秒たったわ！！")
    }
    .disposed(by: disposeBeg)
```

### ログ

```
2秒たったわ！！
2秒たったわ！！
2秒たったわ！！
2秒たったわ！！
2秒たったわ！！
```

# 終わりに
今回はいつも使っている`RxSwift`のオペレーターの紹介をしました。
正直言って全部のオペレーター覚えるの **無理ぽ** ですが慣れるとRxswiftの方が圧倒的に楽だと思います。
コードオンリーでレイアウト組まれている方は特に重宝する技術ではないかと私は思います。
ここまで見ていただきありがとうございます。
少しでも皆様のお役に立てば幸いです。