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 で開発する世界

[YouTube]
https://www.youtube.com/watch?v=6nWnQVRVcs0

[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. View Slide

  2.               
                   ・Rakuten Group, Inc
            
             ・Rakuma
       
       ・iOS Developer
       ・Developer Relations
                 
                   ・Twitter:@hcrane14

    View Slide

  3. 目次

    序章 SwiftUIに対応しよう

    - ラクマのアプリとリファクタリング


    1章 SwiftUIの導入ライン

    - SwiftUIのデメリット


    2章 UIKitからSwiftUIへの移行

    - アーキテクチャー問題

    - 双方向のデータフロー実装

    - 画面のみを移行するケース

    3章 UIKitと画面遷移

    - UIHostingControllerの役割

    - Coordinatorパターンとその拡張

    - FlowControllerについて


    終章

    - 開発のベストプラクティス


    その他・参考文献


    View Slide

  4. View Slide

  5. プロダクトのリファクタリング

    しっかりとやってますか?


    View Slide

  6. View Slide

  7. 今年で10周年のアプリ

    Objective-Cから悲願のSwift対応!


    View Slide

  8. 100%

    66%

    2020/10
 2022/08

    Rakuma iOS App - Swift Percentage 


    View Slide

  9. 次は乗り遅れないために...

    高まるSwiftUIの機運


    View Slide

  10. 現状は...


    View Slide

  11. Rakuma iOS App - UIHostingController Percentage 

    ※1 2022/7 時点

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


    View Slide

  12. どのようにSwiftUIを

    UIKitに入れていくのが良いの?


    View Slide

  13. View Slide

  14. 導入ライン...


    View Slide

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


    View Slide

  16. - 1画面単位で導入する

    - 継続して動的にコンテンツが増えない

    - カスタムViewを作成する必要がない

    ※ 厳密に準拠しているわけではない。

    View Slide

  17. 理由①


    View Slide

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


    View Slide

  19. 対応が困難なUI達


    View Slide

  20. Example

    Design for iPad


    View Slide

  21. Example

    Design for List Separator

    View Slide

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


    View Slide

  23. iOS16+ / NavigationStack 

    Declaration

    Example

    Quote: https://developer.apple.com/documentation/swiftui/navigationstack 


    View Slide

  24. iOS16+ / Grid & GridRow 

    Quote: https://developer.apple.com/documentation/swiftui/grid?changes=_5 


    View Slide

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


    View Slide

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


    View Slide

  27. 理由②


    View Slide

  28. SwiftUIではUIが不十分


    View Slide

  29. じゃあ作る?


    View Slide

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


    View Slide

  31. 独自にカスタマイズした結果...

    - 後々に負債になりうるもの

    - メンテコストがかかるもの

    は作らない方が良い


    View Slide

  32. 例えば...


    View Slide

  33. iOS15+ / refreshable 

    Declaration

    Example

    Quote: https://developer.apple.com/documentation/SwiftUI/View/refreshable(action:) 


    View Slide

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


    View Slide

  35. Example

    `refreshable` extension for Scrollview

    View Slide

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


    View Slide

  37. Example

    `refreshable` extension for iOS14

    View Wrapper 
 UIKit Wrapper 
 ScrollView Wrapper 


    View Slide

  38. View Slide

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


    View Slide

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


    View Slide

  41. View Slide

  42. - UIKitにあるけどSwiftUIにないものは積極的に作らない

     → 今後ネイティブのAPIで提供される可能性が高い


    - ないものは作るしかない

     → アプリ固有でユーザー体験を提供するための機能

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

    View Slide

  43. View Slide

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


    View Slide

  45. 低

    難易度

    View + 遷移

    View + ロジック

    View 全体

    View パーツ

    高


    View Slide

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


    View Slide

  47. 低

    難易度

    View + 遷移

    View + ロジック

    View 全体

    View パーツ

    高

    選択したライン


    View Slide

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


    View Slide

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


    View Slide

  50. UseCase
 Repository

    DataStore

    APIClient

    UIKit

    MVP + Clean Architecture

    ViewController 
 Presenter

    Presenter Protocol 

    ViewController Protocol

    UseCase Protocol 
 Repository Protocol 

    Data Layer
    Protocol


    View Slide

  51. SwiftUIに適していない


    View Slide

  52. UseCase
 Repository

    DataStore

    APIClient

    UIKit

    MVP + Clean Architecture

    ViewController 
 Presenter
 UseCase
 Repository

    DataStore

    APIClient

    Presenter Protocol 

    ViewController Protocol

    Unidirectional Data Flow

    View Slide

  53. Presenter

    ViewController 

    Example

    Unidirectional Data Flow

    ※ 簡易な説明のため initialize は省略

    View Slide

  54. Presenter

    ViewController 

    Input

    Output

    Example

    Unidirectional Data Flow

    View Slide

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


    View Slide

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


    View Slide

  57. 例えば...


    View Slide

  58. Example

    Bidirectional Binding View

    SwiftUI - Textfield 


    View Slide

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


    View Slide

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


    View Slide

  61. - The Composable Architecture(TCA)

    - RIBs

    - ReSwift

    - VIPER

    - MVVM

    etc.


    View Slide

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


    View Slide

  63. プロダクトのリファクタリング

    しっかりとやってますか?


    View Slide

  64. リアーキテクチャーしたものを

    全ての画面にちゃんと実装してますか?


    View Slide

  65. - アーキテクチャーを実装しきった話はほぼ聞かない

    - アーキテクチャーを入れて満足している

    - 継続的なメンテがされていない

    - 導入した人は数年でいなくなっている

    - さらにリアーキテクチャーしてごちゃごちゃ


    View Slide

  66. チームや開発の状況を見て

    一番適したもの検討して導入するべき


    View Slide

  67. チームや開発の状況としては...

    - UIKitの資産を生かしつつ対応可能

    - 双方向のデータフローを許容できる

    これを満たすものを導入したい


    View Slide

  68. ViewController 
 Presenter
 UseCase
 Repository

    DataStore

    APIClient

    UIKit to SwiftUI


    UIKit

    SwiftUI

    ❔


    View Slide

  69. UseCase
 Repository

    DataStore

    APIClient

    ViewController 
 Presenter
 UseCase
 Repository

    DataStore

    APIClient

    Domain / Data Layer

    View Slide

  70. View
 ???

    ViewController 
 Presenter

    UseCase
 Repository

    DataStore

    APIClient

    UseCase
 Repository

    DataStore

    APIClient

    NEW
 NEW

    Presentation Layer

    View Slide

  71. MVVMの採用

    (+ Clearn Architecture)


    View Slide

  72. View
 ???
 UseCase
 Repository

    DataStore

    APIClient

    SwiftUI

    MVVM + Clean Architecture

    NEW

    ViewModel

    NEW


    View Slide

  73. その他の要因

    - MVVMの経験者が複数人在籍しており学習コストが低い

    - 複雑な状態管理を必要する画面がいくつかしかない(not TCA)

    - RouterとSwiftUIの相性が悪い(not VIPER)


    View Slide

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


    View Slide

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


    View Slide

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


    View Slide

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


    View Slide

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


    View Slide

  79. チームや開発の状況を見て

    一番適したもの検討して導入するべき

    (大事なことなので2回目)


    View Slide

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


    View Slide

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


    View Slide

  82. View Slide

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

    View Slide

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

    View Slide

  85. ObservableObjectの仕様で

    SwiftUI上では抽象化したものは使えない

    ※ する方法はあるが、実装を縛れなくなる

    View Slide

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


    View Slide

  87. Example - ViewModel 

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

    View Slide

  88. Example - View


    View Slide

  89. ボイラーテンプレートを

    いい感じにまとめたい


    View Slide

  90. Quote: https://tech.toreta.in/entry/2019/12/24/104612 

    Example1

    SwiftUIとCombineを使ったMVVMの実装

    View Slide

  91. Example2

    marty-suzuki / AnyObservableObject

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


    View Slide

  92. 現状は...


    View Slide

  93. 2020/10

    2022/08

    Rakuma iOS App - Architecture Percentage 

    MVC
    MVC MVP
    MVVM MVP

    View Slide

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


    View Slide

  95. 低

    難易度

    View + 遷移

    View + ロジック

    View 全体

    View パーツ

    高

    軽めに導入ライン


    View Slide

  96. 画面のみSwiftUIにする


    View Slide

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


    View Slide

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

    VIPER architecture


    View Slide

  99. SwiftUI + VIPER architecture


    View Slide

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


    View Slide

  101. View Slide

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


    View Slide

  103. 低

    難易度

    View + 遷移

    View + ロジック

    View 全体

    View パーツ

    高

    選択したライン


    View Slide

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


    View Slide

  105. Bad


    View Slide

  106. Good


    View Slide

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

    Bad


    View Slide

  108. Caution 


    View Slide

  109. UIHostingController
    SwiftUI View
    ViewModel
    Navigation Flow

    Next

    Previous
 Previous

    Next

    Domain / Data
    Layer

    View Slide

  110. UIHostingController
    UIHostingController
    SwiftUI View
    ViewModel
    Processing Flow

    MVVM+α

    Domain / Data
    Layer
    Output
 Input

    Binding


    View Slide

  111. UIHostingController
    SwiftUI View
    ViewModel
    Processing Flow

    ViewModel to UIHostingController

    Output
 Initialize

    Domain / Data
    Layer
    Domain / Data
    Layer

    View Slide

  112. 簡単な例


    View Slide

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

    View Slide

  114. View Slide

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

    View Slide

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


    View Slide

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


    View Slide

  118. ViewController 
 ViewController 

    ViewController 
 ViewController 

    Coordinator
    Coordinator Pattern 


    View Slide

  119. 画面遷移のみを持つ

    UIHostingControllerとの相性が良い


    View Slide

  120. UIHostingController
    SwiftUI View
    ViewModel
    Navigation Flow

    Next

    Previous
 Previous

    Next

    Domain / Data
    Layer

    View Slide

  121. Coordinatorパターンの拡張


    View Slide

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


    View Slide

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


    View Slide

  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/ 


    View Slide

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


    View Slide

  126. UIHostingControllerで実装する


    View Slide

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


    View Slide

  128. 将来的に完全なSwiftUIに寄せたい場合は

    コストになりかねないかも...


    View Slide

  129. View Slide

  130. 2022年において

    UIKitの中でSwiftUIを開発していく

    ベストプラクティスは何?


    View Slide

  131. - SwiftUIで無理なく実装可能な画面のみを対応

    - 画面のみ または 画面+ロジック までをSwiftUIで実装

    - UIHostingControllerを起点として画面遷移


    View Slide

  132. Thank you for listening!


    View Slide

  133. その他・参考文献


    View Slide

  134. iOSDC2021 パンフレット

    「10年目のアプリ リファクタリングと開発」

    View Slide

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


    View Slide

  136. crane-hiromu / SwiftUI-MVVM-HostingController 

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


    View Slide

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


    View Slide

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


    View Slide