rxswift x realm

30
RxSwift x Realm 宇佐見 公輔 2015/9/29 Realm meetup #7

Upload: kosuke-usami

Post on 21-Jan-2017

2.446 views

Category:

Software


2 download

TRANSCRIPT

RxSwift x Realm宇佐見 公輔

2015/9/29 Realm meetup #7

自己紹介• 宇佐見 公輔 (@usamik26) • 大阪府堺市在住

• フェンリル株式会社 • アプリケーション共同開発部 • iOS アプリエンジニア

アドレスバーすら取り払った究極の先端的ブラウザ

今日の内容• RxSwift の紹介

• RxSwift と Realm との連携

RxSwift

Reactive Programming• イベントや値の関係を記述 • 一方の変化を他方に伝播 • メッセージ送信の隠蔽

• データバインディングは Reactive な仕組みの一種

Functional Reactive Programming• 非同期データストリーム • 時間軸に沿って値が流れるリスト

• ストリームに対するリスト操作 • map や filter といった関数型のイディオム

RP / FRP の利点• イベント駆動処理が書きやすい • 非同期処理が書きやすい

• したがって、GUI プログラミングと相性がよい

Reactive Programming for iOS• ReactiveCocoa • ReactKit • RxSwift

• それぞれに良さがある

ReactiveX ファミリー• Rx.NET (C#) • RxJS • RxJava • RxSwift

• ・・・など

RxSwift 2.0• Swift 2 対応版 • バージョン 2.0.0-alpha.3 • iOS 7 以降(iOS 8 以降が望ましい)

• 基本的なところは十分使える状態 • 実案件で採用中

RxSwift の実際

RxSwift / RxCocoa• RxSwift • Observable / 各種 Operator / Scheduler など

• RxCocoa • UIKit / NSURLSession / KVO など

Observable• 非同期データストリームをあらわす

例:イベント処理button.rx_tap .subscribeNext { _ in // ボタンがタップされたときの処理 } .addDisposableTo(disposeBag)

例:非同期処理URLSession.rx_response(request) .subscribeOn(sessionScheduler) .map { (data, response) in // バックグラウンド処理 } .observeOn(mainScheduler) .map { data in // UI処理 }

例:ストリームをつくる:NSURLResponseの場合func rx_response(request: NSURLRequest) -> Observable<NSData!, NSURLResponse!> { return create { observer in // request を送信してレスポンスを受け取る if 失敗 { observer.on(.Error(error)) } else { observer.on(.Next(data, response)) observer.on(.Completed) } return AnonymousDisposable { /* キャンセル処理 */ } } }

例:ストリームをつくる:別の手段let items = PublishSubject<Item>() // Observable<Item>

// データを流す items.on(.Next(item))

// 終了 items.on(.Completed)

// エラー終了 items.on(.Error(error))

例:作ったストリームを使うitems .filter { _ in // 不要なデータを捨てる } .subscribeNext { _ in // データに対する処理 } .addDisposableTo(disposeBag)

RxSwift x Realm

Realm のデータ取得• Realm のクエリでもいいけど・・・

• Rx でデータを取得したい(Observable で扱いたい)

• DB アクセスと Rx の処理が混在すると厄介 • スレッドをまたぐ場合をどうする?

RxJava のケースを参考にする

モデルクラスを分ける• ひとつの対象に対して、ふたつのモデルクラスをつくる • Realm の Object 型のモデル • 非 Realm のモデル

• 冗長であることは否定できない・・・ • DB 用のモデルと View 用のモデル、と思えば許容範囲

仲介役をつくる• RealmDataService • Realm のクエリから Results を得る • Realm の Results から View 用のモデルに変換 • View 用のモデルの Observable を出力

Realm へのアクセス• RealmObservable • Realm へのアクセス処理を一箇所にまとめる

• (前述の RealmDataService で直接 Realm アクセスすることも可能だが、煩雑になる)

使い方RealmDataService.items .map { item in // モデルの処理 } .addDisposableTo(disposeBag)

Realm への書き込み• 同様の枠組みで書き込みにも対応できる

• RealmDataService にデータ作成 I/F を追加 • RealmObservable をトランザクションに対応

まとめ

まとめ• RxSwift の紹介 • RxSwift の実際

• RxSwift と Realm との連携 • 一工夫いれるとよい • Rx と Realm をちゃんと分けて考えるのがよい