【Swift】RxSwift勉強してみたPart1

#はじめに
RxSwiftについて学んだことを自分なりにまとめていこうかと思います。

#GitHub
https://github.com/0429oonishi/RxSwifts

#用語
###Reactive Extensions
オブザーバーパターン、イテレーターパターン、関数型プログラミングの概念を実装したインターフェース。

###オブザーバーパターン
プログラミング内にあるオブジェクトのイベントを他のオブジェクトへ通知する処理で使われるデザインパターンの一種。

###RxSwift
Reactive Extensionsの概念をSwiftで扱えるようにした拡張ライブラリ。
[GitHub](https://github.com/ReactiveX/RxSwift)

###RxCocoa
Reactive Extensionsの概念をUIKitで扱えるようにした拡張ライブラリ。

###リアクティブプログラミング
「時間と共に変化する値」と「振る舞い」の関係を宣言的に記述するプログラミングの手法。

###ストリーム
時間順に並んだ進行中のイベントのこと
[マーブルダイアグラム](https://rxmarbles.com/)

#RxSwiftの特徴
###メリット
値の変化が検知しやすい
非同期処理が簡潔に書ける
時間経過に関する処理をシンプルに書ける
コード全体が一貫する
まとまった流れが見やすい
差分がわかりやすい
処理スレッドを変えやすい
コールバックを減らせる（インデントの浅いコードにできる）

###デメリット
学習コストが高い
デバッグしにくい

#RxSwiftの導入手法
`CocoaPods`, `Carthage`, `SwiftPackageManager`などがある。

#RxSwiftの基本的な書き方
以下のように、メソッドチェーンで書くことができます。

```swift
loginButton.rx.tap
    .subscribe(onNext: { [weak self] in 
        //処理
})
.disposed(by: disposeBag)
```
詳細な説明は後述しますが、大まかな流れは以下のようになります。
1.ストリームの購読
2.ストリームにイベントが流れてきた時にどうするかを定義
3.クラスが破棄されると同時に購読を破棄させるように設定

#実際に書いてみる
実際に書いたコードは[GitHub](https://github.com/0429oonishi/RxSwifts)にあげておきます。今回のコードは`SimpleRxSwift`フォルダにあります。

今回以下のようなものをつくってみましょう。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/be278bf9-3fa2-3396-ca17-a61582d15db7.gif)

`RxSwift`を使わない場合はこんな感じになると思います。

```swift
import UIKit

class SimpleViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func loginButtonDidTapped(_ sender: Any) {
        label.text = "login"
    }
    
    @IBAction func messageButtonDidTapped(_ sender: Any) {
        label.text = "message"
    }
    
    @IBAction func logoutButtonDidTapped(_ sender: Any) {
        label.text = "logout"
    }
    
    @IBAction func backButtonDidTapped(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }
    
}
```

このような書き方は、1つのボタンに1つの関数を定義しています。
ボタンが4つなら関数は4つ用意します。

しかし、`RxSwift`では以下のように書きます。

```swift
import UIKit
import RxSwift
import RxCocoa

class RxSimpleViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var messageButton: UIButton!
    @IBOutlet weak var logoutButton: UIButton!
    @IBOutlet weak var backButton: UIButton!
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        loginButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "login"
            })
            .disposed(by: disposeBag)
        
        messageButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "message"
            })
            .disposed(by: disposeBag)
        
        logoutButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "logout"
            })
            .disposed(by: disposeBag)
        
        backButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.dismiss(animated: true, completion: nil)
            })
            .disposed(by: disposeBag)
        
    }
    
}
```

処理は全く同じでが、コードが全然違いますよね。使わない場合と比べて、UIとコードの制約を一つのプロパティの結合で済むようになっているため、緩くできました。


#おわりに
[次回](https://qiita.com/REON/items/11694c756e51bbbb801b)
RxSwift難しい、、、