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 Foundation
import UIKit
#if !RX_NO_MODULE
import RxSwift
import 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)
}
}
実際にアプリで!!
https:
//github.com
/ReactiveX/RxSwift
こちらがおきまりのリンク先
Observable??
先ほどのa=3にして
b=9になった流れが
Observableです!!
様々な呼び出す関数!!
機能は、今回は割愛!!
●empty
●just
●of
●toObservable
●create
●error
●deffered
そして!!!
自分もコード書きました!!!
https://github.com/daisukenagata/Dban
k/tree/RxRealmTest
usernameOutlet.delegate = self
let 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 in
self.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 in
cell.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 = self
let 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 in
self.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 in
cell.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 = self
let 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 in
self.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 in
cell.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 in
cell.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!!!

Sansan様 登壇資料