{"id":13339182,"url":"https://github.com/fumiyasac/RxSwiftUIExample","last_synced_at":"2025-03-11T12:31:32.562Z","repository":{"id":150267775,"uuid":"159034298","full_name":"fumiyasac/RxSwiftUIExample","owner":"fumiyasac","description":"[ING] - RxSwiftとUI実装の組み合わせサンプル","archived":false,"fork":false,"pushed_at":"2022-02-26T20:32:25.000Z","size":5019,"stargazers_count":18,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-24T00:23:08.374Z","etag":null,"topics":["mvvm-pattern","rxswift","rxswift-examples","ui-design"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fumiyasac.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-25T13:27:01.000Z","updated_at":"2024-04-21T12:09:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"f8175631-b237-4cb8-b5ec-7621a0f9d855","html_url":"https://github.com/fumiyasac/RxSwiftUIExample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumiyasac%2FRxSwiftUIExample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumiyasac%2FRxSwiftUIExample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumiyasac%2FRxSwiftUIExample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumiyasac%2FRxSwiftUIExample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fumiyasac","download_url":"https://codeload.github.com/fumiyasac/RxSwiftUIExample/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243034919,"owners_count":20225429,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mvvm-pattern","rxswift","rxswift-examples","ui-design"],"created_at":"2024-07-29T19:19:19.453Z","updated_at":"2025-03-11T12:31:32.553Z","avatar_url":"https://github.com/fumiyasac.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RxSwiftUIExample\n[ING] - RxSwiftとUI実装の組み合わせサンプル\n\n今回はRxSwiftの実装を改めて思い出すと同時に、実際のUIに当てはめた形でRxSwift+MVVMパターンの構成のサンプルアプリの作成に取り組んでみました。\nUI実装に関しては全体のレイアウトやアニメーション表現に関わる部分で美しい表現でありながらも、今回のサンプル実装以外での応用した活用やカスタマイズがしやすそうなUIライブラリをいくつか利用しています。\n\n### RxSwiftと併せて利用しているMVVMパターンの概要図\n\n![mvvm.png](https://camo.qiitausercontent.com/b619a7738f54a958bd0da42dbbd24acf0142a07b/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f31373430302f36346566386130652d633263662d356438392d383036632d3463353732336434333137392e706e67)\n\n### Storyboard構成図\n\n![storyboard.png](https://qiita-image-store.s3.amazonaws.com/0/17400/f479962b-f2e1-fcb5-f42b-20b1e531da7e.png)\n\n### サンプル画面のキャプチャ\n\n__その1:__\n\n![capture1.png](https://qiita-image-store.s3.amazonaws.com/0/17400/e4fa0446-fac1-3c5d-3739-08dd8472daf1.png)\n\n__その2:__\n\n![capture2.png](https://qiita-image-store.s3.amazonaws.com/0/17400/99948892-ccda-9edb-a038-bffbff246827.png)\n\n### API通信を伴わない部分の実装における概要\n\n__(1) カルーセル状のサムネイル画像表示する画面の処理に関する解説:__\n\n◎ 処理概要\n\n![carousel.png](https://qiita-image-store.s3.amazonaws.com/0/17400/46b639de-8a5a-5aee-b7db-afca95716aa2.png)\n\n◎ 実装に関するポイント\n\n+ __Model:__ 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理については`Decodable`プロトコルを適用しています。\n\n+ __ViewModel:__ 初期化の際にJSONから作成したデータを`Observable\u003c[FeaturedModel]\u003e`型のデータとして保持しておき、UICollectionViewと紐づけられる形にする。また現在の表示しているインデックス値やボタンの表示・非表示に関するステータスを`BehaviorRelay\u003cInt\u003e`型または`BehaviorRelay\u003cBool\u003e`型でイベントを流せる形にしておくと共に、これらの値を更新するためのメソッドを定義しています。\n\n+ __ViewController:__ UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で`private`なメソッドに切り出しておきます。`viewDidLoad`では、RxSwiftを利用してViewModel内で定義している`ViewController側で利用するためのプロパティ`とバインドさせることで、この値の変化に応じたUIの状態が更新される様にしています。\n\n◎ ViewModelとUI部分との関連\n\n![carousel_point.png](https://qiita-image-store.s3.amazonaws.com/0/17400/50dd2869-e928-5098-a2e4-8e12ade68d2d.png)\n\n__(2) ドロップダウンメニューと連動した記事切り替えを伴う画面の処理に関する解説:__\n\n◎ 処理概要\n\n![dropdown.png](https://qiita-image-store.s3.amazonaws.com/0/17400/17af74d3-1d85-884b-c9c2-a56545f48958.png)\n\n◎ 実装に関するポイント\n\n+ __Model:__ 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理については`Decodable`プロトコルを適用しています。\n\n+ __ViewModel:__ 初期化の際にJSONから作成したデータを別途`private`なプロパティで保持しておき、ViewController側で利用するタイトルの一覧を`Observable\u003c[String]\u003e`型のデータを作成してドロップダウンメニューの設定の際に利用できるようにする。またドロップダウンメニューの選択処理で該当のデータを格納する変数`selectedInformation`を`BehaviorRelay\u003cInformationModel?\u003e`型でイベントを流せる形にしておくと共に、これらの値を更新するためのメソッドを定義しています。\n\n+ __ViewController:__ UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で`private`なメソッドに切り出しておきます。`viewDidLoad`では、RxSwiftを利用してViewModel内で定義している`ViewController側で利用するためのプロパティ`とバインドさせることで、この値の変化に応じたUIの状態が更新される様にしています。\n\n◎ ViewModelとUI部分との関連\n\n![dropdown_point.png](https://qiita-image-store.s3.amazonaws.com/0/17400/96c76194-7fd7-5573-46c3-60451f256883.png)\n\n### API通信を伴う部分の実装における概要\n\n__(1) ページネーションを伴って最新のニュースデータから10件ずつ取得して表示する処理:__\n\n◎ 処理概要\n\n![api_request_1.png](https://qiita-image-store.s3.amazonaws.com/0/17400/50109c23-e8ea-7529-1f6d-5e05859ee295.png)\n\n◎ 実装に関するポイント\n\n+ __Model:__ 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理についてはレスポンスが複雑だったので`SwiftyJSON`を利用しています。\n\n+ __ViewModel:__ 初期化の際には前述の`NewYorkTimesProductionAPI.swift`のインスタンスを渡す様にする。ViewController側で`getRecentNews()`メソッドを実行すると、成功時には`BehaviorRelay\u003c[RecentNewsModel]\u003e`型の変数`recentNewsLists`にデータを格納する形にする。また「最初の10件を取得 → 次の10件を取得 → ...」と取得して表示する動きを実現できるような形にしています。（APIでのデータ取得処理結果や状態に関するプロパティについても`BehaviorRelay\u003c[Bool]\u003e`型で定義しています。）\n\n+ __ViewController:__ UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で`private`なメソッドに切り出しておきます。`viewDidLoad`では、RxSwiftを利用してViewModel内で定義している`ViewController側で利用するためのプロパティ`とバインドさせることで、この値の変化に応じたUIの状態が更新される様にすると共に、`MainViewController.swift`に配置している`RecentNewsViewController.swift`を表示しているContainerViewの高さを`RecentNewsViewControllerDelegate`を利用して調整しています。\n\n__(2) フリーワードに該当する記事をインクリメンタルサーチで10件取得して表示する処理:__\n\n◎ 処理概要\n\n![api_request_2.png](https://qiita-image-store.s3.amazonaws.com/0/17400/b61ac78a-9e52-29e0-a7e5-df1cb3c7c5ee.png)\n\n◎ 実装に関するポイント\n\n+ __Model:__ 取得したJSONを定義した型に該当する形にする。初期化時のJSONの解析処理についてはレスポンスが複雑だったので`SwiftyJSON`を利用しています。\n\n+ __ViewModel:__ 初期化の際には前述の`NewYorkTimesProductionAPI.swift`のインスタンスを渡す様にする。ViewController側で`getSearchNews(keyword: String)`メソッドを実行すると、成功時には`BehaviorRelay\u003c[SearchNewsModel]\u003e`型の変数`searchNewsLists`に検索文字列に合致する最大10件のデータを格納する形にしています。（APIでのデータ取得処理結果や状態に関するプロパティについても`BehaviorRelay\u003c[Bool]\u003e`型で定義しています。）\n\n+ __ViewController:__ UIライブラリの初期設定やUI更新に関連する処理を適当な処理粒度で`private`なメソッドに切り出しておきます。`viewDidLoad`では、RxSwiftを利用してViewModel内で定義している`ViewController側で利用するためのプロパティ`とバインドさせることで、この値の変化に応じたUIの状態が更新される様にすると共に、変数`searchBarText`の文字列長さが3未満の場合には`getSearchNews(keyword: String)`メソッド実行しない様な考慮をしています。（別途UIまわりの処理で必要な`UISearchBarDelegate`や`UIGestureRecognizerDelegate`についても記載しています。）\n\n### フローティングメニューボタンの実装\n\n![floating_menu.png](https://qiita-image-store.s3.amazonaws.com/0/17400/0939b16e-cbdf-93c7-2169-d0380d47fd3b.png)\n\n### 利用しているライブラリについて\n\n(1) Rx関連処理を行うために必要なもの\n\n+ [RxSwift \u0026 RxCocoa](https://github.com/ReactiveX/RxSwift)\n\n(2) APIへの非同期通信とJSONの解析を行うために必要なもの\n\n+ [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON)\n+ [Alamofire](https://github.com/Alamofire/Alamofire)\n\n(3) UI表現をするために必要なもの\n\n+ [Floaty](https://github.com/kciter/Floaty)\n+ [DeckTransition](https://github.com/HarshilShah/DeckTransition)\n+ [AnimatedCollectionViewLayout](https://github.com/KelvinJin/AnimatedCollectionViewLayout)\n+ [FontAwesome.swift](https://github.com/thii/FontAwesome.swift)\n+ [BTNavigationDropdownMenu](https://github.com/PhamBaTho/BTNavigationDropdownMenu)\n+ [Toast-Swift](https://github.com/scalessec/Toast-Swift)\n\n### その他\n\nこのサンプル全体の詳細解説とポイントをまとめたものは下記に掲載しております。\n\n(Qiita) https://qiita.com/fumiyasac@github/items/e426d321fbb8ab846bb6\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumiyasac%2FRxSwiftUIExample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffumiyasac%2FRxSwiftUIExample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumiyasac%2FRxSwiftUIExample/lists"}