RxSwiftUIExample
[ING] - RxSwiftとUI実装の組み合わせサンプル
今回はRxSwiftの実装を改めて思い出すと同時に、実際のUIに当てはめた形でRxSwift+MVVMパターンの構成のサンプルアプリの作成に取り組んでみました。 UI実装に関しては全体のレイアウトやアニメーション表現に関わる部分で美しい表現でありながらも、今回のサンプル実装以外での応用した活用やカスタマイズがしやすそうなUIライブラリをいくつか利用しています。
RxSwiftと併せて利用しているMVVMパターンの概要図
Storyboard構成図
サンプル画面のキャプチャ
その1:
その2:
API通信を伴わない部分の実装における概要
(1) カルーセル状のサムネイル画像表示する画面の処理に関する解説:
◎ 処理概要
◎ 実装に関するポイント
-
Model: 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理については
Decodable
プロトコルを適用しています。 -
ViewModel: 初期化の際にJSONから作成したデータを
Observable<[FeaturedModel]>
型のデータとして保持しておき、UICollectionViewと紐づけられる形にする。また現在の表示しているインデックス値やボタンの表示・非表示に関するステータスをBehaviorRelay<Int>
型またはBehaviorRelay<Bool>
型でイベントを流せる形にしておくと共に、これらの値を更新するためのメソッドを定義しています。 -
ViewController: UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で
private
なメソッドに切り出しておきます。viewDidLoad
では、RxSwiftを利用してViewModel内で定義しているViewController側で利用するためのプロパティ
とバインドさせることで、この値の変化に応じたUIの状態が更新される様にしています。
◎ ViewModelとUI部分との関連
(2) ドロップダウンメニューと連動した記事切り替えを伴う画面の処理に関する解説:
◎ 処理概要
◎ 実装に関するポイント
-
Model: 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理については
Decodable
プロトコルを適用しています。 -
ViewModel: 初期化の際にJSONから作成したデータを別途
private
なプロパティで保持しておき、ViewController側で利用するタイトルの一覧をObservable<[String]>
型のデータを作成してドロップダウンメニューの設定の際に利用できるようにする。またドロップダウンメニューの選択処理で該当のデータを格納する変数selectedInformation
をBehaviorRelay<InformationModel?>
型でイベントを流せる形にしておくと共に、これらの値を更新するためのメソッドを定義しています。 -
ViewController: UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で
private
なメソッドに切り出しておきます。viewDidLoad
では、RxSwiftを利用してViewModel内で定義しているViewController側で利用するためのプロパティ
とバインドさせることで、この値の変化に応じたUIの状態が更新される様にしています。
◎ ViewModelとUI部分との関連
API通信を伴う部分の実装における概要
(1) ページネーションを伴って最新のニュースデータから10件ずつ取得して表示する処理:
◎ 処理概要
◎ 実装に関するポイント
-
Model: 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理についてはレスポンスが複雑だったので
SwiftyJSON
を利用しています。 -
ViewModel: 初期化の際には前述の
NewYorkTimesProductionAPI.swift
のインスタンスを渡す様にする。ViewController側でgetRecentNews()
メソッドを実行すると、成功時にはBehaviorRelay<[RecentNewsModel]>
型の変数recentNewsLists
にデータを格納する形にする。また「最初の10件を取得 → 次の10件を取得 → ...」と取得して表示する動きを実現できるような形にしています。(APIでのデータ取得処理結果や状態に関するプロパティについてもBehaviorRelay<[Bool]>
型で定義しています。) -
ViewController: UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で
private
なメソッドに切り出しておきます。viewDidLoad
では、RxSwiftを利用してViewModel内で定義しているViewController側で利用するためのプロパティ
とバインドさせることで、この値の変化に応じたUIの状態が更新される様にすると共に、MainViewController.swift
に配置しているRecentNewsViewController.swift
を表示しているContainerViewの高さをRecentNewsViewControllerDelegate
を利用して調整しています。
(2) フリーワードに該当する記事をインクリメンタルサーチで10件取得して表示する処理:
◎ 処理概要
◎ 実装に関するポイント
-
Model: 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理についてはレスポンスが複雑だったので
SwiftyJSON
を利用しています。 -
ViewModel: 初期化の際には前述の
NewYorkTimesProductionAPI.swift
のインスタンスを渡す様にする。ViewController側でgetSearchNews(keyword: String)
メソッドを実行すると、成功時にはBehaviorRelay<[SearchNewsModel]>
型の変数searchNewsLists
に検索文字列に合致する最大10件のデータを格納する形にしています。(APIでのデータ取得処理結果や状態に関するプロパティについてもBehaviorRelay<[Bool]>
型で定義しています。) -
ViewController: UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で
private
なメソッドに切り出しておきます。viewDidLoad
では、RxSwiftを利用してViewModel内で定義しているViewController側で利用するためのプロパティ
とバインドさせることで、この値の変化に応じたUIの状態が更新される様にすると共に、変数searchBarText
の文字列長さが3未満の場合にはgetSearchNews(keyword: String)
メソッド実行しない様な考慮をしています。(別途UIまわりの処理で必要なUISearchBarDelegate
やUIGestureRecognizerDelegate
についても記載しています。)
フローティングメニューボタンの実装
利用しているライブラリについて
(1) Rx関連処理を行うために必要なもの
(2) APIへの非同期通信とJSONの解析を行うために必要なもの
(3) UI表現をするために必要なもの
- Floaty
- DeckTransition
- AnimatedCollectionViewLayout
- FontAwesome.swift
- BTNavigationDropdownMenu
- Toast-Swift
その他
このサンプル全体の詳細解説とポイントをまとめたものは下記に掲載しております。
(Qiita) https://qiita.com/fumiyasac@github/items/e426d321fbb8ab846bb6