0.9K Views
August 11, 15
スライド概要
Retty Tech Cafe第3回「スタートアップ×iOS開発」で発表した資料に加筆+修正をしたものです
https://atnd.org/events/67600
SwiftとLEGOとBluetooth LEが好きなプログラマ
ReactiveCocoaのゆるい紹介と メルカリでの活⽤用事例例 株式会社メルカリ iOSエンジニア ⼤大庭慎⼀一郎郎
⾃自⼰己紹介 ⼤大庭 慎⼀一郎郎 (ooba / bricklife) 株式会社メルカリ 2013年年4⽉月⼊入社 「メルカリ」iOS版を開発
メルカリとは? いわゆる「フリマアプリ」 2013年年7⽉月 JP版リリース 2014年年8⽉月 US版リリース
はじめに 間違っていても怒怒らないで…! ツッコミは⼤大歓迎です! 先⼈人たちによる偉⼤大なドキュメント からの引⽤用多め
ReactiveCocoaの ゆるい紹介
ReactiveCocoaとは "ReactiveCocoa (RAC) is a Cocoa framework inspired by Functional Reactive Programming. It provides APIs for composing and transforming streams of values over time.” https://github.com/ReactiveCocoa/ReactiveCocoa
Functional Reactive Programming (FRP) とは?
FRPとは 「⾮非同期データストリームを⽤用いた プログラミング」などと説明される ことが多い
よくわかんない\(^o^)/
よくわからないので ReactiveCocoa (RAC) が提供する ものから追っていきたいと思います
RACが提供するもの 1. ストリームを⽣生成する⽅方法 2. ストリームを加⼯工する⽅方法 3. ストリームを監視する⽅方法 +便便利利なマクロ
ようするにRACは ストリームを作ったり使ったり するライブラリ
これがストリームだ! データ 時間 開始 エラー or 完了了 どちらかの発⽣生によって ストリームが終わる
ストリームの⽣生成 RACはCocoaフレームワーク上の様々な ものをストリームに変えられる 例例:⽂文字列列、配列列、KVO、UIイベント、 ネットワーク通信、デリゲートメソッド 呼び出し、etc.
RACが提供するカテゴリ
配列列のストリーム化 [0, 1, 2, 3] 0 1 2 3
タップのストリーム化 タップ ダブルタップ タップ
テキスト⼊入⼒力力のストリーム化 A B C Delete A AB ABC AB
ネットワーク通信のストリーム化 リクエスト 受信中 受信完了 中身は レスポンス
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
ストリームの加⼯工 ストリーム上のデータに対して filter した り map したり merge したり zip したり reduce したりできる オペレータと呼ばれる ここが関数型、すなわちFunctional!
filter http://neilpa.me/rac-marbles/#filter
map http://neilpa.me/rac-marbles/#map
merge http://neilpa.me/rac-marbles/#merge
zip http://neilpa.me/rac-marbles/#zip
reduce http://neilpa.me/rac-marbles/#reduce
例例:ダブルタップのストリーム https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
どんな加⼯工ができるか 「RAC Marbles」やその元の「RxMarbles」を⾒見見る とオペレータの種類とその効果がインタラクティブに わかるのでオススメ http://neilpa.me/rac-‐‑‒marbles/ http://rxmarbles.com/
ストリームの監視 購読 (Subscribe) という ストリームに流流れてくるデータを順次処理理 配列列に戻す、UIへの表⽰示、プロパティの更更新、 画⾯面遷移、etc.
すべてを使ったコードの例例
[[[self.textField rac_textSignal] filter:^BOOL(NSString *value) {
return value.length > 0;
}] subscribeNext:^(NSString *value) {
NSLog(@“%@", value);
}];
-‐‑‒rac_̲textSignal
⼊入⼒力力⽂文字列列からストリームを⽣生成
-‐‑‒filter:
ストリームをfilterして空⽂文字列列が
含まれないように加⼯工
-‐‑‒subscribeNext:
ストリームを購読してログ出⼒力力
便便利利なマクロ RAC(self.label, text) = RACObserve(self, text); たったこれだけで text プロパティの変更更を ラベルに⾃自動反映できる!
ストリームを使ってできること リスト処理理 ⾮非同期イベント処理理 データバインディング Promise MVVM, etc.
なにがうれしいか いろんな⾮非同期処理理を 「ストリームをどう扱うか」 という視点から「宣⾔言的」に記述できる
メルカリでの活⽤用事例例
RAC導⼊入の歴史 2014/8に pod ʻ‘ReactiveCocoaʼ’ 最初に使ったのはUIAlertViewのRACサポート 徐々に適⽤用箇所を広げる 現在iOSエンジニア4⼈人全員がRACを使うように
読み込んだ記事 The introduction to Reactive Programming you've been missing https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 【翻訳】あなたが求めていたリアクティブプログラミ ング⼊入⾨門 http://ninjinkun.hatenablog.com/entry/introrxja
読み込んだ本 「Functional Reactive Programming on iOS」 https://leanpub.com/iosfrp/ 当時の表紙
RACでやっていること リスト処理理 ⾮非同期イベント処理理 データバインディング Promise MVVM, etc.
RACを使っている画⾯面 住所編集画⾯面 ⽀支払い⽅方法選択画⾯面 住所⼀一覧画⾯面 商品⼀一覧画⾯面 銀⾏行行情報編集画⾯面 購⼊入画⾯面 検索索条件選択画⾯面 検索索コーチマーク画⾯面 通知設定画⾯面 検索索サジェスト画⾯面
実際の画⾯面は メルカリをダウンロードして ⾒見見てください!!! https://itunes.apple.com/jp/app/id667861049
データバインディングの例例 銀⾏行行情報編集画⾯面 RAC(self.accountNumberTextField, text) = RACObserve(self.viewModel, accountNumber); プロパティの変更更をテキストフィールドに⾃自動反映 検索索サジェスト画⾯面 RAC(self, inputText) = textField.rac_textSignal; テキストフィールドの変更更をプロパティに⾃自動反映
Promiseの例例 購⼊入画⾯面 RACSignal *timeoutSignal = [[RACSignal merge:@[ _btDataSignal, [RACSignal interval:kBTDataTimeout onScheduler:[RACScheduler mainThreadScheduler]], ]] take:1]; [RACSignal combineLatest:@[_buyAPISignal, timeoutSignal]] subscribeNext:^(RACTuple *tuple) { //... } error:^(NSError *error) { //... }]; タイムアウトを設けた失敗してもよい⾮非同期処理理と 購⼊入APIの完了了を両⽅方待つ
MVVMを導⼊入した画⾯面 住所編集画⾯面 ⽀支払い⽅方法選択画⾯面 住所⼀一覧画⾯面 商品⼀一覧画⾯面 銀⾏行行情報編集画⾯面 購⼊入画⾯面 検索索条件選択画⾯面 検索索コーチマーク画⾯面 通知設定画⾯面 検索索サジェスト画⾯面
MVVMとは Model View ViewModelというMVCの派⽣生パターン https://ja.wikipedia.org/wiki/Model_̲View_̲ViewModel ViewModelはViewを描画するための状態の保持と、 Viewから受け取った⼊入⼒力力を適切切な形に変換してModel に伝達する役⽬目 ViewModelはテストできる!
応⽤用例例:インクリメンタルサーチ
検索索サジェスト画⾯面
以下とほぼ同じ実装をしている
[[[[[textField.rac_textSignal filter:^BOOL(NSString *text) {
return text.length > 0;
}] throttle:0.5] map:^(NSString *text) {
return [[APIClient sharedClient] fetchSearchResultWithQuery:text];
}] switchToLatest] subscribeNext:^(id JSON) {
NSLog(@"Search result: %@", JSON);
}];
http://qiita.com/ikesyo/items/e699eefe1d0985158420
個⼈人的にFRPが本領領発揮するケースの1つだと思う
RAC導⼊入時の注意
導⼊入コストが⾼高い 概念念の理理解に時間がかかる メルカリでは独学と知⾒見見のシェアでなんとかした まずはデータバインディングかPromiseからはじめ るといいかも ⼤大量量のオペレータを理理解する必要がある 関数型⾔言語をやっていればなんとかなるか…?
循環参照しやすい 便便利利マクロ@strongifyと@weakifyを駆使 「Implicit retain of ʻ‘selfʼ’ within blocks」をYesに Instrumentsでメモリの利利⽤用状況をチェック AllocateのMark Generationが便便利利
最初は⼤大変だけど 慣れると楽になってきますよ!
ありがとうございました! スライド内のURL以外に参考にしたURL http://havelog.ayumusato.com/develop/javascript/e657-‐‑‒ reactive_̲programming_̲in_̲javascript.html http://qiita.com/amay077/items/5e7cedb069a5a6ae0ae7 http://yohshiy.blog.fc2.com/blog-‐‑‒entry-‐‑‒215.html http://www.slideshare.net/taketin/mvvm-‐‑‒40956834