67
Reactive Extensions (Rx)

Sansan様 登壇資料

Embed Size (px)

Citation preview

Reactive Extensions

(Rx)

マイクロソフト社

開発

Rxは、2009年11月18日からマイクロソフト

のボータルサイトが

解説されていた。

様々に活用される関数型言語

例えば

その前に!!

私は誰ですか?

iosエンジニアです。漫画アプリ、RealmSDK、セキュリティアプリ、ニュースアプリ、カメラアプリ、アキパス相続税アプリ、

RxSwift

RxJava

RxJs

ReactKit

RxCocoa

SwiftBond

ReactiveCocoa

RxRealm

SwiftbondだけRxではないけど

関数型言語です。

本日は何をするか?

関数型言語で全般的に使える

思考、解釈、コード発表。

RXのデザインパターンは

Observerpattern

Observerpattern

とは?

監視対象のオブジェクトを観測者オブジェクト

が監視していて、監視対象が変化したのを観

測者が確認したら特定のアクションを起こすの

が基本です。

例えば

Var a = 2

let b = a*3

b = 6

Var a = 2

let b = a*3

b = 6

 そこに a = 3 にすると

b=9になります。

実際にコードで!!

import Foundationimport UIKit#if !RX_NO_MODULEimport RxSwiftimport RxCocoa#endif

class NumbersViewController: ViewController { @IBOutlet weak var number1: UITextField! @IBOutlet weak var number2: UITextField! @IBOutlet weak var number3: UITextField!

@IBOutlet weak var result: UILabel!

override func viewDidLoad() { super.viewDidLoad()

Observable.combineLatest(number1.rx_text, number2.rx_text, number3.rx_text) { textValue1, textValue2, textValue3 -> Int in return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0) + (Int(textValue3) ?? 0) } .map { $0.description } .bindTo(result.rx_text) .addDisposableTo(disposeBag) }}

実際にアプリで!!

Observable??

先ほどのa=3にして

b=9になった流れが

Observableです!!

様々な呼び出す関数!!

機能は、今回は割愛!!

●empty

●just

●of

●toObservable

●create

●error

●deffered

そして!!!

usernameOutlet.delegate = selflet usernameValid = usernameOutlet.rx_text

.map { $0 == self.userName}

.shareReplay(1)usernameValid

.bindTo(usernameValidOutlet.rx_hidden)

.addDisposableTo(disposeBag)

let url = "http://api.gnavi.co.jp/RestSearcht=json=name"/*Observable<Results<Lap>> - wrap Results as observable*/realm.objects(Lap).asObservable()

.map {laps in "\(laps.count) laps"}

.subscribeNext {[unowned self]text inself.title = text

}.addDisposableTo(disposeBag)

/*Observable<Array<Lap>> - convert Results to Array and wrap as observable*/realm.objects(Lap).sorted("time", ascending: false).asObservableArray()

.map {array in array.prefix(2) }

.bindTo(tableView.rx_itemsWithCellIdentifier("Cell", cellType: UITableViewCell.self)) {row, element, cell incell.textLabel!.text = formatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: element.time))Alamofire.request(.GET, url)

.responseJSON { response in}.addDisposableTo(disposeBag)

addOneItemButton.rx_tap.map { Lap() }.bindTo(Realm.rx_add()).addDisposableTo(disposeBag)

}

何のコード???

usernameOutlet.delegate = selflet usernameValid = usernameOutlet.rx_text

.map { $0 == self.userName}

.shareReplay(1)usernameValid

.bindTo(usernameValidOutlet.rx_hidden)

.addDisposableTo(disposeBag)

let url = "http://api.gnavi.co.jp/RestSearcht=json=name"/*Observable<Results<Lap>> - wrap Results as observable*/realm.objects(Lap).asObservable()

.map {laps in "\(laps.count) laps"}

.subscribeNext {[unowned self]text inself.title = text

}.addDisposableTo(disposeBag)

/*Observable<Array<Lap>> - convert Results to Array and wrap as observable*/realm.objects(Lap).sorted("time", ascending: false).asObservableArray()

.map {array in array.prefix(2) }

.bindTo(tableView.rx_itemsWithCellIdentifier("Cell", cellType: UITableViewCell.self)) {row, element, cell incell.textLabel!.text = formatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: element.time))Alamofire.request(.GET, url)

.responseJSON { response in}.addDisposableTo(disposeBag)

addOneItemButton.rx_tap.map { Lap() }.bindTo(Realm.rx_add()).addDisposableTo(disposeBag)

}

RxRealm

提供する反応コレクション型の非常に薄いラッ

パーです。

usernameOutlet.delegate = selflet usernameValid = usernameOutlet.rx_text

.map { $0 == self.userName}

.shareReplay(1)usernameValid

.bindTo(usernameValidOutlet.rx_hidden)

.addDisposableTo(disposeBag)

let url = "http://api.gnavi.co.jp/RestSearcht=json=name"/*Observable<Results<Lap>> - wrap Results as observable*/realm.objects(Lap).asObservable()

.map {laps in "\(laps.count) laps"}

.subscribeNext {[unowned self]text inself.title = text

}.addDisposableTo(disposeBag)

/*Observable<Array<Lap>> - convert Results to Array and wrap as observable*/realm.objects(Lap).sorted("time", ascending: false).asObservableArray()

.map {array in array.prefix(2) }

.bindTo(tableView.rx_itemsWithCellIdentifier("Cell", cellType: UITableViewCell.self)) {row, element, cell incell.textLabel!.text = formatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: element.time))Alamofire.request(.GET, url)

.responseJSON { response in}.addDisposableTo(disposeBag)

addOneItemButton.rx_tap.map { Lap() }.bindTo(Realm.rx_add()).addDisposableTo(disposeBag)

}

realm.objects(Lap).asObservable()

コレクションが

変更するたびに発行します。

.shareReplay(1)

Hot変換オペレータの1つ!

Hot???

Hotって何?

ストリームを内の変換名称

HotとColdがあります。

Hotはストリームを稼働さ

せる性質

Rxのストリームは基本的にSubscribeされた瞬間に各オペレータの動作が始まるようになっています。

ですがHot Observableをストリームの途中に挟むことで、Subscribeを実行するより前にストリームを稼働させることができます。

Subscribeされるまで動作

しない性質

Cold Observableは、Subscribeされる(またはHot変換される)まで動作しないObservableです。稼働していないCold Observableに渡されたメッ

セージは全て処理すらされることなく消滅してしまいます。

で、何で.shareReplay(1)?

replayとrefCountという2つのオペレーターについて知る必要があります。

引用しました。

realm.objects(Lap).sorted("time", ascending: false).asObservableArray()

.asObservableArray()?

collection上のarray方式を使用する場合など

配列の値に変換します。

今回のサンプルアプリケーションは、

配列に代入するBlock文の中に、

合わせてJsonから取得した情報をデータに書

き込みました。

/*Observable<Array<Lap>> - convert Results to Array and wrap as observable*/realm.objects(Lap).sorted("time", ascending: false).asObservableArray()

.map {array in array.prefix(2) }

.bindTo(tableView.rx_itemsWithCellIdentifier("Cell", cellType: UITableViewCell.self)) {row, element, cell incell.textLabel!.text = formatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: element.time))Alamofire.request(.GET, url)

.responseJSON { response in

こちらにJsonデータ

を代入しています。

}.addDisposableTo(disposeBag)addOneItemButton.rx_tap

.map { Lap() }

.bindTo(Realm.rx_add())

.addDisposableTo(disposeBag)}

実際に動かします。JsonのURL設定する際に、ぐるなび登録する

必要があります。

感じた利点。

可読性、保守性

反射性、汎用性

今後の課題

なぜ必要か?を明確にすること

気づいたこと

Sansan様で登壇する際は、BackGroundColorはWhiteにすること。

Thank you Sansan!!!