2.3K Views
July 25, 23
スライド概要
potatotips #83 iOS/Android開発Tips共有会での登壇資料です。
画面遷移のアーキテクチャー検討について potatotips #83 iOS/Android開発Tips共有会 yoshitaka
yoshitaka iOS エンジニア ・鉄道会社の社内アプリ ・CtoCのマッチングプラットフォームアプリ ・現在)コネヒト:出産育児系のQAアプリ ママリ https://tech.connehito.com/entry/2023/07/07/192756
話すこと • 画面遷移のアーキテクチャー • それぞれの違い • まとめ
画面遷移のアーキテクチャー導入を検討するうえで • MVVMの構成 • 画面遷移はViewControllerが担当 • 実装コストとメリットで導入判断したい • SwiftUI化も見据えた形にできたら良さそう
「iOSアプリ設計パターン入門」の中で 4.4 モバイルアプリにおけるアーキテクチャ - 画面遷移について ・CoordinatorパターンとMVVM-C ・RouterパターンとVIPER などが挙げられていました Coordinatorパターンの派生系 ・FlowController パターン
Coordinatorパターン ・画面遷移ロジックを画面実装から引き剥がすデザインパターン ・再利用性を高め、ViewController同士が密結合することを防ぐ
Viewが画面遷移を行う場合 class FirstViewController: UIViewController { private func buttonTapped() { let vc = SecondViewController() self.navigationController?.pushViewController(vc, animated: true) } }
Coordinatorパターン protocol Coordinator { func start() } protocol FirstViewControllerDelegate: AnyObject { func firstViewControllerDidTapButton() } class FirstViewController: UIViewController { weak var delegate: FirstViewControllerDelegate? private func buttonTapped() { delegate?.firstViewControllerDidTapButton() } }
Coordinatorパターン class FirstViewCoordinator: Coordinator { let navigator: UINavigationController var firstViewController: FirstViewController? var secondViewCoordinator: SecondViewCoordinator? init(navigator: UINavigationController) { self.navigator = navigator } func start() { let firstViewController = FirstViewController() firstViewController.delegate = self self.navigator.viewControllers = [firstViewController] self.firstViewController = firstViewController } } extension FirstViewCoordinator: FirstViewControllerDelegate { func firstViewControllerDidTapButton() { let secondViewCoordinator = SecondViewCoordinator(navigator: self.navigator) secondViewCoordinator.start() self.secondViewCoordinator = secondViewCoordinator } }
Coordinatorパターン class FirstViewCoordinator: Coordinator { let navigator: UINavigationController var firstViewController: FirstViewController? var secondViewCoordinator: SecondViewCoordinator? init(navigator: UINavigationController) { self.navigator = navigator } func start() { let firstViewController = FirstViewController() firstViewController.delegate = self self.navigator.viewControllers = [firstViewController] self.firstViewController = firstViewController } } extension FirstViewCoordinator: FirstViewControllerDelegate { func firstViewControllerDidTapButton() { let secondViewCoordinator = SecondViewCoordinator(navigator: self.navigator) secondViewCoordinator.start() self.secondViewCoordinator = secondViewCoordinator } }
Routerパターン ・特定の画面遷移のロジックをカプセル化し、 ViewControllerが直接画面遷移を管理する代わりにRouterオブジェクトに委任 ・VIPERが有名
Routerパターン protocol FirstViewRouterProtocol: AnyObject { func transitionToSecondView() } final class FirstViewRouter: FirstViewRouterProtocol { private(set) weak var view: UIViewController! init(view: UIViewController) { self.view = view } func transitionToSecondView() { let vc = SecondViewController() view.navigationController?.pushViewController(vc, animated: true) } } class FirstViewController: UIViewController { private var router: FirstViewRouterProtocol! private func buttonTapped() { router.transitionToFirstTabSecond() } }
まとめ • Coordinatorパターン・Routerパターンどちらにしても各ViewControllerご とにCoordinator・Routerを定義する必要があり導入コストは高そう • SwiftUI化した場合には再度画面遷移のアーキテクチャーの構成は変わりそう
ご清聴ありがとうございました