Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSDC2022 - SwiftUI in UIKit で開発する世界

h.crane
September 12, 2022

iOSDC2022 - SwiftUI in UIKit で開発する世界

[Conference]
iOSDC Japan 2022

[Title]
SwiftUI in UIKit で開発する世界

[Proposal]
https://fortee.jp/iosdc-japan-2022/proposal/d824fc5d-191a-4864-899a-339d830ed182

h.crane

September 12, 2022
Tweet

More Decks by h.crane

Other Decks in Technology

Transcript

  1. None
  2.                <Company>                ・Rakuten Group, Inc          <Application>          ・Rakuma

       <Role>    ・iOS Developer    ・Developer Relations               <Account>                ・Twitter:@hcrane14
  3. 目次
 序章 SwiftUIに対応しよう
 - ラクマのアプリとリファクタリング 
 
 1章 SwiftUIの導入ライン
 -

    SwiftUIのデメリット
 
 2章 UIKitからSwiftUIへの移行
 - アーキテクチャー問題
 - 双方向のデータフロー実装
 - 画面のみを移行するケース
 3章 UIKitと画面遷移
 - UIHostingControllerの役割
 - Coordinatorパターンとその拡張 
 - FlowControllerについて
 
 終章
 - 開発のベストプラクティス
 
 その他・参考文献

  4. None
  5. プロダクトのリファクタリング
 しっかりとやってますか?


  6. None
  7. 今年で10周年のアプリ
 Objective-Cから悲願のSwift対応!


  8. 100%
 66%
 2020/10
 2022/08
 Rakuma iOS App - Swift Percentage

  9. 次は乗り遅れないために...
 高まるSwiftUIの機運


  10. 現状は...


  11. Rakuma iOS App - UIHostingController Percentage 
 ※1 2022/7 時点


    ※2 画面数の割合ではないので注意

  12. どのようにSwiftUIを
 UIKitに入れていくのが良いの?


  13. None
  14. 導入ライン...


  15. SwiftUIで無理なく実装可能な画面


  16. - 1画面単位で導入する
 - 継続して動的にコンテンツが増えない
 - カスタムViewを作成する必要がない
 ※ 厳密に準拠しているわけではない。 


  17. 理由①


  18. iOSDC2021「Compositional Layoutsで実現する疎結合な実装 」より


  19. 対応が困難なUI達


  20. Example
 Design for iPad


  21. Example
 Design for List Separator 


  22. WWDC2022で発表された新しいAPI


  23. iOS16+ / NavigationStack 
 Declaration
 Example
 Quote: https://developer.apple.com/documentation/swiftui/navigationstack 


  24. iOS16+ / Grid & GridRow 
 Quote: https://developer.apple.com/documentation/swiftui/grid?changes=_5 


  25. 少しずつ改善されてる!


  26. けど、本格運用は2年後くらい...


  27. 理由②


  28. SwiftUIではUIが不十分


  29. じゃあ作る?


  30. Quote: https://qiita.com/noppefoxwolf/items/5b65ab3d62acd83a79cc 


  31. 独自にカスタマイズした結果...
 - 後々に負債になりうるもの
 - メンテコストがかかるもの
 は作らない方が良い


  32. 例えば...


  33. iOS15+ / refreshable 
 Declaration
 Example
 Quote: https://developer.apple.com/documentation/SwiftUI/View/refreshable(action:) 


  34. ScrollViewでは使えないので拡張する


  35. Example
 `refreshable` extension for Scrollview 


  36. iOS14では使えないので拡張する


  37. Example
 `refreshable` extension for iOS14 
 View Wrapper 
 UIKit

    Wrapper 
 ScrollView Wrapper 

  38. None
  39. 次のアップデートで...


  40. Quote: https://twitter.com/clarko/status/1552383186604216321 


  41. None
  42. - UIKitにあるけどSwiftUIにないものは積極的に作らない
  → 今後ネイティブのAPIで提供される可能性が高い
 
 - ないものは作るしかない
  → アプリ固有でユーザー体験を提供するための機能
  ex

    カルーセル、カメラ、動画、広告 etc. 

  43. None
  44. どこまで移行するのか問題


  45. 低
 難易度
 View + 遷移
 View + ロジック
 View 全体


    View パーツ
 高

  46. UIKitの資産を生かしつつ移行したい


  47. 低
 難易度
 View + 遷移
 View + ロジック
 View 全体


    View パーツ
 高
 選択したライン

  48. アーキテクチャーの問題


  49. 現在採用しているアーキテクチャー


  50. UseCase
 Repository
 DataStore
 APIClient
 UIKit
 MVP + Clean Architecture 


    ViewController 
 Presenter
 Presenter Protocol 
 ViewController Protocol
 UseCase Protocol 
 Repository Protocol 
 Data Layer Protocol

  51. SwiftUIに適していない


  52. UseCase
 Repository
 DataStore
 APIClient
 UIKit
 MVP + Clean Architecture 


    ViewController 
 Presenter
 UseCase
 Repository
 DataStore
 APIClient
 Presenter Protocol 
 ViewController Protocol
 Unidirectional Data Flow
  53. Presenter
 ViewController 
 Example
 Unidirectional Data Flow 
 ※ 簡易な説明のため

    initialize は省略 

  54. Presenter
 ViewController 
 Input
 Output
 Example
 Unidirectional Data Flow 


  55. 単一方向だけで問題なかった


  56. SwiftUIは双方向のデータフローが必須


  57. 例えば...


  58. Example
 Bidirectional Binding View 
 SwiftUI - Textfield 


  59. Viewによっては双方向な実装を強制される


  60. SwiftUIは違うアーキテクチャーを検討する


  61. - The Composable Architecture(TCA)
 - RIBs
 - ReSwift
 - VIPER


    - MVVM
 etc.

  62. ここで今一度考えて欲しい


  63. プロダクトのリファクタリング
 しっかりとやってますか?


  64. リアーキテクチャーしたものを
 全ての画面にちゃんと実装してますか?


  65. - アーキテクチャーを実装しきった話はほぼ聞かない
 - アーキテクチャーを入れて満足している
 - 継続的なメンテがされていない
 - 導入した人は数年でいなくなっている
 - さらにリアーキテクチャーしてごちゃごちゃ


  66. チームや開発の状況を見て
 一番適したもの検討して導入するべき


  67. チームや開発の状況としては...
 - UIKitの資産を生かしつつ対応可能
 - 双方向のデータフローを許容できる
 これを満たすものを導入したい


  68. ViewController 
 Presenter
 UseCase
 Repository
 DataStore
 APIClient
 UIKit to SwiftUI


    
 UIKit
 SwiftUI
 ❔

  69. UseCase
 Repository
 DataStore
 APIClient
 ViewController 
 Presenter
 UseCase
 Repository
 DataStore


    APIClient
 Domain / Data Layer
  70. View
 ???
 ViewController 
 Presenter
 UseCase
 Repository
 DataStore
 APIClient
 UseCase


    Repository
 DataStore
 APIClient
 NEW
 NEW
 Presentation Layer
  71. MVVMの採用
 (+ Clearn Architecture)


  72. View
 ???
 UseCase
 Repository
 DataStore
 APIClient
 SwiftUI
 MVVM + Clean

    Architecture 
 NEW
 ViewModel
 NEW

  73. その他の要因
 - MVVMの経験者が複数人在籍しており学習コストが低い
 - 複雑な状態管理を必要する画面がいくつかしかない(not TCA)
 - RouterとSwiftUIの相性が悪い(not VIPER)


  74. アプリのアーキテクチャー全体像


  75. Quote: https://qiita.com/karamage/items/8a9c76caff187d3eb838 


  76. アーキテクチャーの共存


  77. Quote: https://qiita.com/karamage/items/8a9c76caff187d3eb838 


  78. どのアーキテクチャーがベストとかはない


  79. チームや開発の状況を見て
 一番適したもの検討して導入するべき
 (大事なことなので2回目)


  80. SwiftUIにおけるMVVMの実装は?


  81. 既存のスタンダードな実装方法


  82. None
  83. ※ 簡易な説明のため一部は省略しています 


  84. ※ 簡易な説明のため一部は省略しています 


  85. ObservableObjectの仕様で
 SwiftUI上では抽象化したものは使えない
 ※ する方法はあるが、実装を縛れなくなる 


  86. 他の方法で実装を管理する


  87. Example - ViewModel 
 ※ 簡易な説明のため一部は省略しています 


  88. Example - View


  89. ボイラーテンプレートを
 いい感じにまとめたい


  90. Quote: https://tech.toreta.in/entry/2019/12/24/104612 
 Example1
 SwiftUIとCombineを使ったMVVMの実装 


  91. Example2
 marty-suzuki / AnyObservableObject 
 Quote: https://github.com/marty-suzuki/AnyObservableObject 


  92. 現状は...


  93. 2020/10
 2022/08
 Rakuma iOS App - Architecture Percentage 
 MVC

    MVC MVP MVVM MVP
  94. もう少し軽めにSwiftUIを導入したい場合


  95. 低
 難易度
 View + 遷移
 View + ロジック
 View 全体


    View パーツ
 高
 軽めに導入ライン

  96. 画面のみSwiftUIにする


  97. Quote: https://techlife.cookpad.com/entry/2021/01/18/kaimono-swift-ui 


  98. Quote: https://tech.toreta.in/entry/2019/12/24/104612 
 VIPER architecture


  99. SwiftUI + VIPER architecture


  100. UIKitの資産をそのまま持ってこれる


  101. None
  102. 画面遷移をどうするか


  103. 低
 難易度
 View + 遷移
 View + ロジック
 View 全体


    View パーツ
 高
 選択したライン

  104. UIHostingControllerを親画面とした画面遷移


  105. Bad


  106. Good


  107. UIViewController UIViewController UIHostingController SwiftUI View ViewModel Domain / Data Layer

    UIHostingController SwiftUI View ViewModel Domain / Data Layer Good
 Bad

  108. Caution 


  109. UIHostingController SwiftUI View ViewModel Navigation Flow
 Next
 Previous
 Previous
 Next


    Domain / Data Layer
  110. UIHostingController UIHostingController SwiftUI View ViewModel Processing Flow
 MVVM+α
 Domain /

    Data Layer Output
 Input
 Binding

  111. UIHostingController SwiftUI View ViewModel Processing Flow
 ViewModel to UIHostingController 


    Output
 Initialize
 Domain / Data Layer Domain / Data Layer
  112. 簡単な例


  113. ※ 簡易な説明のため一部は省略しています 


  114. None
  115. Output Initialize ※ 簡易な説明のため一部は省略しています 


  116. もう少し踏み込んで実装したい場合


  117. Coordinatorパターンによる実装


  118. ViewController 
 ViewController 
 ViewController 
 ViewController 
 Coordinator Coordinator

    Pattern 

  119. 画面遷移のみを持つ
 UIHostingControllerとの相性が良い


  120. UIHostingController SwiftUI View ViewModel Navigation Flow
 Next
 Previous
 Previous
 Next


    Domain / Data Layer
  121. Coordinatorパターンの拡張


  122. FlowControllerと画面遷移のコントロール


  123. Quote: https://ocollet.com/2014/02/06/flow-controller/ 


  124. > One of the first rules a developer learns is

    to separate the code handling the data and the user interface. The link between the data and UI is usually done in a controller, or, in iOS, a view controller. In most projects, view controllers are interconnected and can be very dependent with one another. That’s where the flow controller comes in. It serves as a link between view controllers. It’s the brain of the app.
 Quote: https://ocollet.com/2014/02/06/flow-controller/ 

  125. Quote: https://github.com/onmyway133/blog/issues/106 


  126. UIHostingControllerで実装する


  127. Quote: https://qiita.com/hugehoge/items/b28f134bc4806d584892 


  128. 将来的に完全なSwiftUIに寄せたい場合は
 コストになりかねないかも...


  129. None
  130. 2022年において
 UIKitの中でSwiftUIを開発していく
 ベストプラクティスは何?


  131. - SwiftUIで無理なく実装可能な画面のみを対応
 - 画面のみ または 画面+ロジック までをSwiftUIで実装
 - UIHostingControllerを起点として画面遷移


  132. Thank you for listening!


  133. その他・参考文献


  134. iOSDC2021 パンフレット 
 「10年目のアプリ リファクタリングと開発」 


  135. Quote: https://speakerdeck.com/darquro/rakuma-swiftui-introduction-policy-and-tips 


  136. crane-hiromu / SwiftUI-MVVM-HostingController 
 Quote: https://github.com/crane-hiromu/SwiftUI-MVVM-HostingController 


  137. Quote: https://qiita.com/shiz/items/4a828dc8e4eb0c96d397 


  138. Quote: https://qiita.com/hugehoge/items/b28f134bc4806d584892