RxSwiftのexampleをコードで書く（その１）

#はじめに
コードのみでRxSwiftのexampleを書き直しました
(レイアウトはsnapKitをつかっております)
### exampleその１
TextFiledに数字を入れると、一番下のラベルに３つの値の合計が即座に計算されるexample
<img width="326" alt="screenshot.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/5d372051-76ad-43e2-9608-521c4f3cbab2.png">


# 環境構築
## プロジェクトファイルを作る
名前は何でもいいですが今回の例では`RxSwift_for_code`としてます

## podfileの編集

```
$ vi Podfile
```

Podfileの中身
`target 'RxSwift_for_code' do`の`RxSwift_for_code`をプロジェクトファイルで使った名前にしてください

```
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'

use_frameworks!

target 'RxSwift_for_code' do
    pod 'RxSwift',    '~> 4.0'
    pod 'RxCocoa',    '~> 4.0'
    pod 'SnapKit', '~> 4.0.0'
end
```

## Podfileに登録したライブラリをおとしてくる (bundlerでcocoapodを管理しているためpodのコマンドを使うときはbundle execを前につける必要がある)

```
$ pod install
```

## このときに作られた`RxSwift_for_code.xcworkspace`を起動する
`ViewController.swift`を開いて下記コードをコピペでうごきます

# コードの中身
`ViewController.swiftのなかみ`

```Swift 
import UIKit
import RxSwift
import RxCocoa
import SnapKit

class ViewController: UIViewController {
    var disposeBag = DisposeBag()

    var number1: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .roundedRect
        return textField
    }()
    var number2: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .roundedRect
        return textField
    }()
    var number3: UITextField = {
        let textField = UITextField()
        textField.borderStyle = .roundedRect
        return textField
    }()

    var label: UILabel = {
        let label = UILabel()
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(self.number1)
        self.number1.snp.makeConstraints { (make) -> Void in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top).offset(100)
            make.centerX.equalTo(self.view)
        }
        self.view.addSubview(self.number2)
        self.number2.snp.makeConstraints { (make) -> Void in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.top.equalTo(self.number1.snp.bottom)
            make.centerX.equalTo(self.view)
        }
        self.view.addSubview(self.number3)
        self.number3.snp.makeConstraints { (make) -> Void in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.top.equalTo(self.number2.snp.bottom)
            make.centerX.equalTo(self.view)
        }
        self.view.addSubview(self.label)
        self.label.snp.makeConstraints { (make) -> Void in
            make.width.equalTo(200)
            make.height.equalTo(50)
            make.top.equalTo(self.number3.snp.bottom)
            make.centerX.equalTo(self.view)
        }

      //観測可能なシーケンスのいずれかが要素を生成するたびに、セレクタ関数を使用して、指定された観測可能なシーケンスを1つの観測可能なシーケンスにマージします。
//orEmpty:`String？`型のコントロールプロパティを `String`型のコントロールプロパティに変換します。
Observable.combineLatest(number1.rx.text.orEmpty,number2.rx.text.orEmpty,number3.rx.text.orEmpty) { textValue1, textValue2, textValue3 -> Int in
            return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0) + (Int(textValue3) ?? 0)
        }
        //入ってきた値をStringに変換する関数
        .map { $0.description}
        //新しいサブスクリプションを作成し、オブザーバに要素を送信します。
        .bind(to: label.rx.text)
        .disposed(by: disposeBag)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

```

# 理解のための自分なりの解釈
Observableに連なっていくのは処理の一連の流れなのだと思う
## CombineLatestという関数
この関数は観測する値（この例だったらUITextFiledのtextの値）を複数入れて一つのデータの流れにする関数なのだと思う

```
public static func combineLatest<O1, O2, O3>(_ source1: O1, _ source2: O2, _ source3: O3, resultSelector: @escaping (O1.E, O2.E, O3.E) throws -> Self.E) -> RxSwift.Observable<Self.E> where O1 : ObservableType, O2 : ObservableType, O3 : ObservableType
```

ちなみに上の関数の定義をみてみると第四引数であるresultSelectorはクロージャーを受け取る引数である。
一番最後の引数でクロージャーの場合、上の例のように外にはみ出して連なることができる

つまり第４引数はこれである
textValue1はO1.E、textValue2はO2.E、textValue3はO3.Eにあたり途中でString型はIntに変換されクロージャー内の処理が終わる(Self.E→Intになるんですね)

```
{ textValue1, textValue2, textValue3 -> Int in
            return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0) + (Int(textValue3) ?? 0)
        }
```

## number1.rx.text.orEmptyのorEmpty
orEmpty:`String？`型のコントロールプロパティを `String`型のコントロールプロパティに変換します。
UITextFiledに入ってるのか入っていないのかわからない値であるためString?というのが前提条件だと思うのだが、このデータの流れに入る際はString型に変換してくれる便利な関数ということらしい

## $0.description
直前のクロージャーの処理を抜けるとInt型のデータがながれてくる
map関数は流れたデータそれぞれに処理を行う関数である.
クロージャー内の引数は$0と表しても良いので、クロージャー内でIntに変換されたされた値(たとえば$0=14というような値)がはいってくる
$0.descriptionのようにdescriptionをつなげると、$0で入ってきた値をString型に変換してくれる
(例 14(Int)→"14"(String))

##.bind(to: label.rx.text)
最後にbind関数に入る

```
public func bind<O>(to observer: O) -> Disposable where O : ObserverType, O.E == Self.E?
```
引数はobserver型のなにかの型　返り値はDisposableで入ってくるデータと同じ型である必要がある　またObserverTypeの要素をもつ型である必要がある

Stringに変換した値は、UILabelクラスのインスタンスであるlabelのtextに入れるということらしい

##.disposed(by: disposeBag)
最後に流れ着いた先の値の返り値は前の段階でDisposableになっているはず
これは、処理が終わった後は観測を辞める必要があるとのことでおまじないのようにつけている感覚
(いつかきちんと理解したら書きたい)