はじめに
N予備校 iOS アプリ 開発チームでは、長い間 UIKit & Storyboard & RxSwift & MVVM で開発してきました。
以前から「Storyboard やめたい!」「SwiftUI 書きたい!」「Xcode Previews を使って効率よく開発したい!」といった思いが強く、SwiftUI を導入したい気持ちがありました。
ですが、昨年まではアプリのサポートOSが iOS 13.0+ だったこともあり、SwiftUI で苦しむことを危惧していました。
2022年3月末、ついに iOS 14.0 未満のサポートを終了しました。
2022年2月頃から2022年10月現在までに、SwiftUI 導入を実現する為にどのようなことを検討・実践してきたのかをご紹介します。
導入に向けて検討したこと
流れ
- UIKit 及び Storyboard をどのように置き換えるのか
- 書き慣れた MVVM パターンを維持できるのか
- 既存のプロジェクト構成でもスムーズに導入できるのか
- アプリのサポートOSが iOS14.0+ だが、 SwiftUI 特有の苦しみは問題なさそうか
- 本当に開発効率は向上できるのか
1. UIKit 及び Storyboard をどのように置き換えるのか
「全てを SwiftUI で作り直す」という目標は立てませんでした。
主な理由は、画面遷移を実現する NavigationView
及び NavigationLink
のバグが多く扱い辛い点です。
画面遷移に関しては既存実装を活かすことにしたので、 今後も ViewController
を使います。
実装方針は以下のようにしました。
- 既存の
ViewController
で実装されているView
の実装は削除- IBOutlet で接続しているプロパティは全て削除
- Storyboard を削除
- UIKit の世界に SwiftUI を持ってくるため、UIHostingController を使う
2. 書き慣れた MVVM パターンを維持できるのかどうか
TCA の採用も少し検討しましたが、現在採用しているアーキテクチャとは全くの別物です。
最終的に、クックパッドさんの記事 を参考にさせていただきました。
シンプルな画面であれば、ViewController に実装されている ViewModel と Rx のコードをほぼそのまま残し、ViewModel で取得したデータのバインド先を差し替える程度で済みそうでした。
SwiftUI 以外の学習コストを極力増やさない方向で考えていたので、引き続き MVVM パターンで実装する方針としました。
採用した実装のイメージ
// SwiftUI View struct SettingView: View { final class DataSource: ObservableObject, ReactiveCompatible { @Published var hasError: Bool init(...) { ... } } @ObservedObject var dataSource: DataSource var body: some View { if hasError { errorView } else { contentView } } } // ViewController final class SettingViewController: UIViewController { ... override func viewDidLoad() { ... let hostingViewController = UIHostingViewController(rootView: SettingView(...)) ... viewModel.outputs.hasError .drive(dataSource.rx.hasError) .disposed(by: disposeBag) } }
3. 既存のプロジェクト構成でもスムーズに導入できるのか
アプリのサポートOS が iOS 14.0+ なので、最初から SwiftUI 2 が使用できる状態でした。
上述の 1.
と 2.
の方針によって部分的な SwiftUI 移行が実現できる為、初期導入コストもほとんど払わずに済みました。
4. アプリのサポートOSが iOS14.0+ だが、 SwiftUI 特有の苦しみは問題なさそうか
検討開始当時は、アプリのサポートOSは iOS13.0+ でした。
「あって当然」と考えている機能が用意されていなかったりしたので、逆に開発効率は下がると判断し、SwiftUI の導入を渋っていました。
しかし、 2021年9月の時点で、2022年3月下旬に iOS14 未満のサポート終了することが決定しています。
N予備校フォーラムでの告知
この事から、前向きに SwiftUI の導入の検討を始めました。
iOS13.0+ ほどではないにしても、 iOS14.0+ でも多少は苦しむだろうと覚悟していました。
(alert や actionSheet が iOS15.0+ で非推奨になったり、etc)
5. 本当に開発効率は向上できるのか
諸々調査・検討した結果、 開発効率向上は見込める と判断できました。
ピックアップした一部の判断材料は下記の通りです。
- 複雑怪奇な Storyboard を編集する必要がなくなった
- 制約の張り方が無秩序で手に負えない
- Storyboard や Xib (自動生成XML)は読みにくく、コードレビューがつらい
- SwiftUI だと人間が書くので、読みやすかったり、コードの意図を教えてくれたり
- 自動生成XML vs 人間が書いた Swift コード
- プレビューが非常に便利!
- SwiftUI コードを書いている隣でプレビュー表示してくれる
⚠️ 10分経ってもプレビュー表示されない場合は諦める(潔く諦めるのも大事。実行して確認すればOK。)
⚠️ プレビュー時に謎のエラーが出る場合は Xcode を再起動してみる(諦めないのも大事。再起動するだけで最高の体験が得られるかも。)
導入決定後から本格対応までにやったこと
流れ
- 画面構成がシンプルで、利用頻度の低い設定画面の SwiftUI 化
- チーム勉強会の時間を使って一緒に学習
1. 画面構成がシンプルで、利用頻度の低い設定画面の SwiftUI 化
SwiftUI 化の第一弾は設定画面に決定しました。
画面構成がシンプルかつ要素が少ないので、取っ掛かりとしてはちょうどよかったです。
ただ、標準の List だと罫線の描画が想定通りにいかない問題がありました。
他にも幾つか懸念点があったので、 ScrollView + LazyVStack でリストを実装する方針にしました。
標準の List で困った例
List { Section { // 罫線の色が変更できない(iOS 15.0+ ならできる) Text("text1") .listRowSeparatorTint(Color.red) // 罫線の表示/非表示が変更できない(iOS 15.0+ ならできる) Text("text2") .listRowSeparator(.hidden) } }
2. チーム勉強会の時間を使って一緒に学習
N予備校iOSチームでは、毎週木曜日に30分枠で勉強会を実施しています。
今年5月下旬から12営業日はほぼ連続で、SwiftUI 勉強会を実施しました。(1回あたり1時間)
Apple 公式の SwiftUI チュートリアルを読み合わせながら、チュートリアル通りにコードを書いて理解していきました。
ただなぞるだけでなく、気になった箇所をぱぱっと調べて情報共有もしていました。
思いの外時間が掛かりましたが、共通の不明点がその場で解消できてよかったです。
実践
移行計画
まずは、移行対象となる画面を決める条件を以下のように設定しました。
- 比較的シンプルであること(パーツ数が少ない、ビジネスロジックがシンプル、etc)
- 直近の案件で改修対象となっていない
次に、移行順を決める条件を以下のように設定しました。
- 移行が原因で万が一問題が発生しても、ユーザー影響が小さい順
- 移行対応の着手が可能な時期
検討の結果、以下の順番で移行を進めていくことにしました。
- 設定画面
- 通知画面(運営からのお知らせ一覧)
- フォーラムTOP画面(フォーラムに投稿された質問の一覧)
- 授業TOP画面(放送前・放送中・放送後の授業の一覧)
- フォーラム検索画面(フォーラムに投稿された質問や回答を検索)
- 授業検索画面(放送前・放送中・放送後の授業を検索)
※ 他の画面についても現在検討中です。
※ 新規で画面を作る場合は、最初から SwiftUI で作ります。
成果
2022年10月現在、以下の画面が SwiftUI 移行を完了しています。
- 設定画面
- 通知画面
- フォーラムTOP画面
現在、他の画面も鋭意開発中です!
おわりに
実践していくなかで見えてきた新たな課題があり、都度 SwiftUI と格闘することがあります。
iOS 14 系と iOS 15 系で動作や見た目に差異があったりするので、それを吸収したコンポーネントを作ったり、入念に動作確認しています。
それでも、開発・レビュー・改修のやりやすさは格段に向上し、「SwiftUI を導入して良かった!」 と感じています。
今後も、SwiftUI を活用した開発に取り組んでいきます。
We are hiring!
株式会社ドワンゴの教育事業では、一緒に未来の当たり前の教育をつくるメンバーを募集しています。
カジュアル面談も行っています。 お気軽にご連絡ください!
開発チームの取り組み、教育事業の今後については、他の記事や採用資料をご覧ください。