Slide 1

Slide 1 text

@motoshima1150 iOSDC 2023 SwiftUIの進化に ついていくためにやったこと

Slide 2

Slide 2 text

このセッションのねらい 『スタディサプリ 中学講座』がSwiftUIと共に歩んできた道を振り返りました。 ポイント1 直面した課題の例として 具体的にAlert, NavigationViewの進化を知る SwiftUIのような進化の早いフレームワークと どのように付き合うのかを考える ポイント2

Slide 3

Slide 3 text

Agenda | 01 02 03 04 発表者紹介 SwiftUIと『スタディサプリ 中学講座』 SwiftUIの実践的な書き換え まとめ

Slide 4

Slide 4 text

発表者紹介 01

Slide 5

Slide 5 text

@motoshima1150 / 中島元成 - iOS アプリエンジニア - 『スタディサプリ 中学講座』開発を担当 - 🍺, 🏕, 󰴢 "3dメガネ アイコン" by DesignBolts is licensed underCC BY 4.0

Slide 6

Slide 6 text

(株)リクルートでの位置づけ 創業 本社 事業の売上収益 従業員数 2012年 10月1日 株式会社リクルートホールディングス設立時の 分社化により設立 2018年 4月1日 株式会社リクルートに商号変更 東京 7,606億円 (2022年4月1日~2023年3月31日) 19,836人 (2023年4月1日現在 / アルバイト・パート含) OUR VISION

Slide 7

Slide 7 text

サービスラインナップ 様々なサービスラインナップにて事業展開をしています スタディサプリ 対象学年 小・中学校 高校 大学・社会人 オンラインビデオ (B to C) オンラインビデオ& アセスメント (B to B to C) オンラインコーチング パーソナルコーチプラン

Slide 8

Slide 8 text

SwiftUIと『スタディサプリ 中学講座』 02

Slide 9

Slide 9 text

SwiftUI 年表 と『スタディサプリ 中学講座』 WWDC19 WWDC20 WWDC21 WWDC22 WWDC23 SwiftUI発表 SwiftUIベースのアプリ構築が可能に Listや検索の大幅強化 .searchable modifierの追加 .refreshable modifierの追加 .swipeActions modifierの追加 NavigationStackの追加 Charts フレームワークの追加 Photos フレームワークの追加 KeyframeAnimation @Observable の追加 MapKit の強化 SwiftDataのサポート リニューアルリ リース リニューアル 開始

Slide 10

Slide 10 text

『スタディサプリ 中学講座』はSwiftUIと共に歩んでいる

Slide 11

Slide 11 text

どのような課題が発生したか ● 既存実装が非推奨となり、将来的に廃止されてしまう ○ Alert, NavigationLink ● 新規APIが公開されるが、対応バージョン要件を満たせず導入できない ○ NavigationStack Alert, Navigationのケースで書き換えをご紹介いたします

Slide 12

Slide 12 text

… 『スタディサプリ 中学講座』の構成 スタディサプリ 中学講座 project Core: 依存関係や共通処理を持つ UIComponent: 共通UIやDesignSystem の token などを持つ JuniorHighSchool: 実際の画面単位でサブモジュールを用意 MyPage StudyReport … マルチモジュール構成に移行中。各モジュール間は独立した実装が可能になっています。  コラム

Slide 13

Slide 13 text

SwiftUIの実践的な書き換え 03

Slide 14

Slide 14 text

@State private var showAlert = false var body: some View { Button("Tap to show alert") { showAlert = true } .alert(isPresented: $showAlert) { Alert( title: Text("Current Location Not Available"), message: Text("Your current location can’t be " + "determined at this time.") ) } } struct Login: View {すprivate var didFail = false let alertTitle: String = "Login failed." var body: some View { LoginForm(didFail: $didFail) .alert( alertTitle, isPresented: $didFail ) { Button("OK") { // Handle the acknowledgement. } } } } ● Alert viewが廃止となり、より扱いやすくなっている。 Alert の進化 iOS 13.0–17.0 Deprecated iPadOS 13.0–17.0 Deprecated https://developer.apple.com/documentation/swiftui/ iOS 15.0+ iPadOS 15.0+

Slide 15

Slide 15 text

『スタディサプリ 中学講座』でのAlert用途 ● ユーザーに向けて通信エラーを伝える ● 学習を離脱するなどのユーザー状態が破棄される前の確認 ● 強制バージョンアップやメンテナンスなどの強制力の強いユーザー告知

Slide 16

Slide 16 text

Alert の書き換え .background( EmptyView().alert( isPresented: $isFirstAlertPresented, content: { Alert(title: Text("First alert"), message: Text("Alert message")) } ) ) .alert( "First alert", isPresented: $isFirstAlertPresented, actions: { }, message: { Text("Alert message") } ) 旧APIでは1つのViewに対して、複数のAlert modifierを付与した際に表示されない動作の 回避として利用

Slide 17

Slide 17 text

NavigationView Navigation APIの進化 iOS 13.0–17.0 Deprecated iPadOS 13.0–17.0 Deprecated iOS 16.0+ iPadOS 16.0+ @State private var isShowingPurple = false @State private var isShowingPink = false @State private var isShowingOrange = false var body: some View { NavigationView { List { NavigationLink("Purple", isActive: $isShowingPurple) { ColorDetail(color: .purple) } NavigationLink("Pink", isActive: $isShowingPink) { ColorDetail(color: .pink) } NavigationLink("Orange", isActive: $isShowingOrange) { ColorDetail(color: .orange) } } } .navigationViewStyle(.stack) } // Nothing on the stack by default. @State private var path: [Color] = [] var body: some View { NavigationStack(path: $path) { List { NavigationLink("Purple", value: .purple) NavigationLink("Pink", value: .pink) NavigationLink("Orange", value: .orange) } .navigationDestination(for: Color.self) { color in ColorDetail(color: color) } } } https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types NavigationStack

Slide 18

Slide 18 text

『スタディサプリ 中学講座』でのNavigation用途 ● Push遷移(2−3階層) ● プログラムで制御された Push遷移 ● 1画面から複数の種類の遷移先

Slide 19

Slide 19 text

NavigationView → NavigationStack の書き換え NavigationView { CourseScreen() } struct CourseScreen: View { ... @State var isActive = false @State var selectedTopicID = "" var body: some View { ZStack { NavigationLink(isActive: $isActive) { TopicScreen(topicID: selectedTopicID) } label: { EmptyView() } VStack { ForEach(course.topicIDs, id: \.self) { id in Button("topic id: \(id)") { selectedTopicID = id isActive = true } } } } ... } } NavigationStack { CourseScreen() } struct CourseScreen: View { ... @State var isActive = false @State var selectedTopicID = "" var body: some View { VStack { ForEach(course.topicIDs, id: \.self) { id in Button("topic id: \(id)") { selectedTopicID = id isActive = true } } } .navigationDestination(isPresented: $isActive) { TopicScreen(topicID: selectedTopicID) } ... } } 不自然なZStackとNavigationLinkが消えてスッキリ

Slide 20

Slide 20 text

運用状況

Slide 21

Slide 21 text

1. Issueを作成し、課題としてチーム内共有する。 2. 動作確認の担保、書き換え方針を共有する。 3. 品質改善の時間で実際にコードの書き換えを行う。 計画

Slide 22

Slide 22 text

● 課題をオープンにすることで、以下のメリットを受けています。 ○ 目につくので忘れない ○ いつでも見返せる ○ 対応時期のコミュニケーションが容易 1. Issueを作成し、課題としてチーム内共有する。

Slide 23

Slide 23 text

● MagicPodを用いたE2Eテストを導入しています。 ○ 画面遷移などの書き換えも安心して書き換えができます。 ● 書き換えの方針などを事前共有によってチーム内で検証します。 2. 動作確認の担保、書き換え方針を共有する。

Slide 24

Slide 24 text

私たちのチームでは品質改善に向けた実装時間が確保されています。 ● Quality Budget ○ 2週間に1日品質改善に寄与する issueを消化する日を設けています。 ● KAIZEN ○ 小中高プロダクトiOSチームでプロダクトを跨いでペアを組み、 週に1回1時間程度品質改善に当てる。 3. 品質改善の時間で実際にコードの書き換えを行う。

Slide 25

Slide 25 text

● 『スタディサプリ』は年に1回バージョン更新を行なっています。 ○ 今年の4月にiOS 14をサポートバージョンから外しました。 ○ シェア率を参照しながらPdMとすり合わせを行い更新しています。 ● これから導入を控えているもの。 今後の予定は https://developer.apple.com/documentation/swiftui/navigationstack https://developer.apple.com/documentation/swiftui/view/presentationdetents(_:)

Slide 26

Slide 26 text

まとめ 04

Slide 27

Slide 27 text

私たちはSwiftUIの進化を追いながら、落ち着いて取捨選択ができたと思います。 書籍「進化的アーキテクチャ」と照らし合わせ要因を振り返りました。 要因 ● 年一回のサポートバージョンの見直しタイミングがある ○ 腐敗防止層の対策が立てやすい ● モジュール分割により、新しいコードは新しい設計で書くことができる ○ 漸進的な改善を行うことができる ● メインタスクとは別で品質改善のために取り組む時間がある ○ 心理的にも余裕が生まれる 運用を通しての振り返り

Slide 28

Slide 28 text

最後に『スタディサプリ 中学講座』で得たまなび 私たちのSwiftUIという選択は、2020年時点では将来性のリスクを取ることだったと思 います。 導入時点ではどれも予測のつかない変化でしたが、その点で過剰に忌避するのでは なく、ワークアラウンドな対応なども受け入れながらSwiftUIの進化に合わせて一緒に 進化しつつ、導入タイミングはプロダクトでハンドリングできる基盤を整えておくことの 重要性を改めてまなぶことができました。

Slide 29

Slide 29 text

その他 弊社についてのご紹介 以下リンク先でもプロダクト開発部について紹介しています。ぜひご覧ください。 ・スタディサプリ プロダクトチーム ブログ  スタディサプリ Product Team Blog  発表資料 - スタディサプリ Product Team Blog  ※エンジニア / デザイナー / TPMが記事を書いています ・ブランドサイト  スタディサプリ BRAND SITE ・採用ページはこちら   キャリア | スタディサプリ BRAND SITE ・カジュアル面談はこちらからお気軽にご応募ください   スタディサプリエンジニア職種カジュアル面談エントリーフォーム

Slide 30

Slide 30 text

一緒に事業拡大を目指す仲間を お待ちしています!

Slide 31

Slide 31 text

ご清聴ありがとうございました