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の破棄タイミングでこのフローも破棄されるようにしています。