Upload
fumiya-sakai
View
572
Download
2
Embed Size (px)
Citation preview
RxSwiftでの実装練習の記録ノートと
はじめの一歩
potatotips#37
2017/02/15FumiyaSakai
自己紹介と簡単な経歴など
✦ 今までの仕事履歴(本業)
石川県金沢市生まれ
本業はサーバーサイドのプログラマ※Rails&PHP使い
26歳〜32歳: Webプログラマ(PHP&Rubyがキャリア長い)
23歳〜25歳: Webデザイナー兼ディレクター
2017年3月よりiOSアプリ開発のエンジニアになります。
趣味:シルバーアクセサリー集め・スイーツ作り・アプリ開発
女子向け・グルメ・エンタメ関連のお仕事が多い
Qiita:http://qiita.com/fumiyasac@github
Github:https://github.com/fumiyasac
✦ 酒井文也(さかいふみや)
東京(大塚)住まいの32歳
こんな格好を普段からしているので遊び人に見られますがエンジニアです。
文系卒に思われますが実は数学科で理系卒です。
めっちゃお酒好きそうに見えますがビール苦手でお酒も超弱いです。
今でもたまにUIまわりとか触りたくなることがあったりなかったり
今年の4月からフリーランスです。(割とお堅い感じの会社にいます)
最近のはまっている食べ物はカボチャと担々麺と甘栗です。
最近はSwift以外ではRailsやLaravel・CakePHP・Node.jsなんかも
これまでに作ったもの(ネイティブアプリ)
①簡易家計簿アプリ「Coffre」
②ゲームアプリ「10秒虫食い算」
・カレンダーを自作しています
・シンプルなお小遣い帳感覚で支出管理できます
・全問正解者ほとんどいません…
・不定期ですがコラムも書いています
・サーバーサイドはRubyonRailsを使用
http://www.coffre.me/
・デザインにもこだわってみました(特にグラフ)
・実はちょっとバグがあります。
・問題は今後追加予定(現在110問収録)
個人的にはなりますが、他にもアプリ・Webサービスなど開発中です(2016年も宜しくお願いします)
・サイト等は次回のアップデートで公開予定
http://blog.just1factory.net/services/284
・若干の中毒性を含みます
カレンダーが好きでライブラリを作りました
日本の祝祭日を計算で出してくれる
・カレンダーアプリ等での活用を想定
・シルバーウィーク・ゴールデンウィークも対応
・ハッピーマンデー法の施行も対応
・春分の日・秋分の日にも対応
・過去の祝祭日もおおむね考慮はしている
構想や基本実装は僕ですが、他に4名のContributorのお力添えがあり実運用できるレベルになりました!
CocoaPods&Carthage&手動で導入可能
・HTTP(HTTPS)通信は不要
★CalculateCalendarLogicver0.1.2
【2017年】Swift3系への正式対応をしていますので是非README等を参考に導入してみてください!
・Github:https://github.com/fumiyasac/handMadeCalendarAdvance
・実装解説:http://qiita.com/fumiyasac@github/items/33bfc07ad36dfffcdf8f
・Github:https://github.com/fumiyasac/handMadeCalendarOfSwift
新機能や運用保守は継続しています
✦ サンプルを見ては見るけどどこから手をつけていいかわからない
RxSwiftに最初は苦手意識があった
思った以上に最初の「とっかかり」部分から一歩前へ出るまでに時間がかかってしまった。
今回は閑話休題にはなりますが、こんな感じでRxSwiftに取り組みましたという自分自身のお話しになります。
★基本のさらにさわりの部分は聞いたことがあるけど…のレベル
・MVVMの構成に関してはサーバーサイドでも同様のフレームワークを業務で使用した経験はあった
★知っているだけでは全然手がつけられない
【苦手意識があると想像以上に手が出せないスパイラル…】
・RxSwiftの勉強会には何度か参加をしたことはあった
しかしながら、実践がなかったので後回し×N回のような形になっていた。
・ちょうど良い分量のサンプル(最初に無理なく取り組む)を見つけるのがちょっと大変…
・Qiitaや技術ブログ等を調べてみるとObserverパターンやAPI通信に関する例が多かった
とりあえずは写経のような形でできるところはほんの少しだけアレンジする方針ですすめてみよう。
✦ まずはObserverパターンを試してみて次にDriverパターンをする
苦手意識の克服のためにやってみたこと
最初にポピュラーそうなものを動画と一緒に取り組んでみると苦手意識を薄めることができたように思う。
★この順番で取り組んだ理由
★前編と後編に分けてアプローチしてみる
・サンプルやQiitaを始め技術ブログで実装例や解説資料がこの2つのパターンが多かった
前編:ObserverパターンとUITableView関連
・UIまわりの実装に関連するような処理が比較的多そうな印象があった
UIに絡む処理やAPIを活用する処理であれば実際に近しいので挫折しにくいと思った。
後編:Driverパターン+MVVM+API通信系
・できるだけまずは日本語で作成するサンプル構成や要点になるものをまとめることにした。
【RxSwiftに少しでも歩み寄るために試してみたこと】
通信が起こらないものでまずは作ってみる
・ソースコードの中にもできるだけコメントや参考リンクを残す形でコードにしてみた。
・前編の2サンプルに関しては動画も併用して取り組んでみた。
APIクライアントを使用した入力値との同期検索
✦ 今回は前編と後編のドキュメントとQiitaを交えて解説していきます
今回のサンプルと詳細解説はこちら
Observerパターンで使用するメソッドや観測対象に登録した定数値に関する加工処理の扱いがポイントに。
前編のサンプルに関して:
・複数のテキストフィールドやボタンの入力値の変化のハンドリングをRxSwiftで行うようにする
・いつも書き慣れたUITableViewの記述をRxSwiftに置き換えてみるとどのような形になるか確認
ポイント:
★通信を伴わないObserverパターン
準備体操)入力を簡単に色々やってみよう!
テキストフィールドやボタンの状態や入力値を観
測対象としてそれぞれの値の変化をキャッチして
値を加工して表示する。
実装1)ラーメン写真を表示しよう!
UITableViewの実装におけるDataSourceの部分を
RxDataSourcesを利用して実装しデータの一覧を
表示する。
※View-Presenter-Modelで役割分割を含む
✦ 今回は前編と後編のドキュメントとQiitaを交えて解説していきます
今回のサンプルと詳細解説はこちら
UIとの値のバインド(結合)を行うタイミングでDriverに変換をすることでUIと関連する処理をしやすくする。
後編のサンプルに関して:
・RxSwift+MVVMを利用してAPI通信のハンドリングを制御&データの流れの関係性を整理する
・UIの処理を行うタイミングの手前でDriverに変換をすることでUIまわりの処理をしやすくする
ポイント:
★API処理+MVVMを使ったDriverパターン
実装2)リポジトリ検索サンプル(RxExample引用)
Githubのユーザー名を検索してそのユーザーに紐
づくリポジトリ名の一覧を表示する。
※RxAlamofireを活用したサンプル
実装3)FourSquare検索サンプル(@koogawaさん作)
FoursquareAPIClientを利用して場所名を検索して
キーワードに該当する施設や飲食店の情報を取得
して一覧を表示する。
※FoursquareAPIClient+少し自分でアレンジ
✦ 今回の例で自分が感じたこういうケースの際に便利かなという所感
RxSwiftなしの場合だと処理やデータ取得までの流れの管理がアプリが大きくなるにつれて散漫になりがち。
★今回の作成したサンプルから感じたもの
もしもRxSwiftがなかったら…(想像)
・ObserverパターンでUIから受け取る値のハンドリングと加工処理
★今回の詳細解説資料
・UITableViewのRxSwift化
・MVVM構成でフローの整理とDriverへの変換
http://qiita.com/fumiyasac@github/items/90d1ebaa0cd8c4558d96
・RxSwiftでの実装練習の記録ノート(前編:Observerパターンの例とUITableViewの例)
http://qiita.com/fumiyasac@github/items/da762ea512484a8291a3
・RxSwiftでの実装練習の記録ノート(後編:DriverパターンとAPIへの通信を伴うMVVM構成のサンプル例)
https://github.com/fumiyasac/RxSwiftPracticeNote
・今回収録したサンプルのリポジトリ
Delegateメソッドだけで行うと値の加工処理等が複雑になりそうだけどこれなら関係性も掴み易い
使用用途は限定されそうな気もするがDatasource周りの記述がスッキリできる部分は良さそうかも
お互いの役割を明確にし受け取った値の変化を整理した上で処理をするので見通しが良くなりそう
✦ Observerパターンの基本的な構文と使い方を押さえておく
この書き方が良いのかは若干自信がないのですが、観測対象の定数に対して順繰りに値を加工・整形する。
挨拶文を作るプラクティスの実装ポイント
//セグメントコントロールにおいて、値変化のイベントを観測対象にする let segmentedControlObservable: Observable<Int> = stateSegmentedControl.rx.value.asObservable() //セグメントコントロールの値変化を検知して、その状態に対応するenumの値を返す //(map)別の要素に変換する ※IntからStateへ変換 let stateObservable: Observable<State> = segmentedControlObservable.map { (selectedIndex: Int) -> State in return State(rawValue: selectedIndex)! }
//enumの値変化を検知して、テキストフィールドが編集を受け付ける状態かを返す //(map)別の要素に変換する ※StateからBoolへ変換 let greetingTextFieldEnabledObservable: Observable<Bool> = stateObservable.map { (state: State) -> Bool in return state == .useTextField }
//(bindTo)イベントのプロパティ接続をする ※bindToの引数内に表示対象のUIパーツを設定 //(DisposeBag)観測状態からの解放を行う greetingTextFieldEnabledObservable.bindTo(freeTextField.rx.isEnabled).addDisposableTo(disposeBag)
終端で観測状態の解除を行う
この中で観測対象の定数に対して処理を行なう(SegmentControlの状態)
★それぞれの定数を.asObservable()で観測対象とし、その値に対して加工を行う
この中で観測対象の定数に対して処理を行なう(入力モードの変換)
✦ RxSwiftを用いることで下記のように書くことも可能
RxDatasourcesを使用して最終的にbindToでデータと紐づける(PresenterからのデータはすでにObservable)
UITableViewのDataSource部分の実装ポイント
//データソースを元にしてセルの生成を行う dataSource.configureCell = {_, tableView, indexPath, ramens in let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = ramens.name cell.detailTextLabel?.text = ramens.taste cell.imageView?.image = ramens.image return cell }
//作成したデータと表示するUITableViewをBindして表示する ramensData.ramens.bindTo(ramenTableView.rx.items(dataSource: dataSource)).addDisposableTo(disposeBag)
//RxSwiftを利用してUITableViewDelegateを適用する ramenTableView.rx.setDelegate(self).addDisposableTo(disposeBag)
//データソースの定義を元にセクションヘッダーを生成する ※動画サンプルと形式が違う部分 dataSource.titleForHeaderInSection = { (ds, section: Int) -> String in return ds[section].model }
//データソースの定義 let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Ramen>>()
//Presenter層から表示するラーメンデータの取得 let ramensData = RamenPresenter()
★DataSource部分はRxTableViewSectionedDataSource<SectionModelを活用して記述
✦ UIとデータのバインドをして入力値変更に伴って表示も変更する
APIとの通信が絡むようなUI関連の更新の際にはObservableだけだと面倒な考慮もDriver変換でし易くする。
★後編のサンプルでの役割の構成のまとめ
DriverパターンとMVVM構成の概要
View層 ViewModel層 Model層
①テキストフィールドの入力を検知 ②入力された値を条件にAPIへリクエスト
③受取ったレスポンスをマッピングや整形④UIとのバインドを行うタイミングでDriverに変換
・メインスレッドで観測状態にするのでUIの更新に関する考慮がすでにされている
・ObservableだけではErrorまたはCompletion時に処理の流れが途切れるのでそれを防止する
Driverパターンのポイントやメリットをざっくりまとめ:
各種階層の役割まとめ:
・(View層)データとUIとのバインドしてデータの変化に応じた表示を行う
・(ViewModel層)View層でのUI変化の受け取りやレスポンスに対する値の変換処理等の中継
・(Model層)MappingされたEntity群やAPI通信に関連するビジネスロジックがある
✦ まずは解きやすいサンプルやパターンから紐解いてみる
今回のまとめ
ご清聴ありがとうございました!またこのような機会があった際には是非ともよろしくお願い致します!
★はじめのいっぽはObserverパターンとDriverパターンから始めると良いかも
適度にUIが絡むサンプルを自分で見たり写経して要点をまとめるようにすると理解が深まるかと
★RxSwiftなしでの実装も一緒に考えて見るとさらに理解が深まる
多くの入力要素が絡むケースの処理やMVVM等の大きなアプリケーションになった場合のことをイメージ
★動画を見ながらコードを書いて自分なりの解説や参考資料をまとめる
実装コードだけでなく「なぜその設計やライブラリを使うのか」という部分も垣間見ることができる
★自分ルール
【良いアウトプットのために】
発表・登壇時はこの中のいずれか2つを
絶対に準備するルールを設けています!