Pebble's Diary

プログラマーの作業メモ

RxSwift 超入門その1

0)環境: Xcode8.2.1

1) 新規iOSプロジェクトaaaを作成する。

2) aaaフォルダに新規ファイルPackage.swiftを以下の内容で作成する。

import PackageDescription

let package = Package(
    name: "dummy",
    targets: [], 
    dependencies: [
        .Package(url: "https://github.com/ReactiveX/RxSwift.git", majorVersion: 3)
    ]
)

3) aaaフォルダで

$ swift build

を実行する。エラーが出るが気にしない。

4) aaa.xcodeprojに、Packages/RxSwift-3.2.0/Rx.xcodeprojを追加し、
aaa.xcodeprojのターゲットaaaの
Target Dependencies
RxCocoa-iOS,RxSwift-iOSの2つを追加する。
Link Binary With Libraries
にもRxCocoa-iOS,RxSwift-iOSを追加し、ビルドする。

5) aaa.xcodeprojのMain.storyboardにUITextLabelを2つとUILabel一つを追加する。

6) ViewControllerの先頭に以下のソースを追加する。

import RxSwift
import RxCocoa

7) ViewControllerに以下のソースを追加し3つの@IBOutletを接続して実行する。

import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
    @IBOutlet weak var field1:UITextField!
    @IBOutlet weak var field2:UITextField!
    @IBOutlet weak var label:UILabel!
    var disposeBag = DisposeBag()
    override func viewDidLoad() {
        super.viewDidLoad()
        Observable.combineLatest(field1.rx.text.orEmpty,
                                 field2.rx.text.orEmpty) {
                                    textValue1, textValue2 -> Int in
                return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0)
            }
            .map { $0.description }
            .bindTo(label.rx.text)
            .disposed(by: disposeBag)
    }
}

解説:
.rxはUITextFieldやUILabelなどUIKitのコントロールに追加されたswift extensionです。
combineLatestは2つの引数を持ちますが、2つの引数のどちらかに変化が発生した時に、イベントを発生させます。
その時、2つの引数の最新の値を利用してクロージャが実行され、以降の.mapの処理へと続きます。
このフローは、このViewControllerが破棄された時に不要となるため、このViewControllerのメンバ変数であるdisposeBagを使って.disposed(by:)することによって、ViewControllerの破棄タイミングでこのフローも破棄されるようにしています。