Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
SwiftUIの進化に ついていくためにやったこと
Search
Recruit
PRO
August 31, 2023
Business
6
5.2k
SwiftUIの進化に ついていくためにやったこと
iOSDC Japan 2023 での中島の発表資料です。
Recruit
PRO
August 31, 2023
Tweet
Share
More Decks by Recruit
See All by Recruit
あなたの知らない Linuxカーネル脆弱性の世界
recruitengineers
PRO
3
170
dbtとBigQuery MLで実現する リクルートの営業支援基盤のモデル開発と保守運用
recruitengineers
PRO
3
180
『ホットペッパービューティー』のiOSアプリをUIKitからSwiftUIへ段階的に移行するためにやったこと
recruitengineers
PRO
4
1.6k
経営の意思決定を加速する 「事業KPIダッシュボード」構築の全貌
recruitengineers
PRO
4
290
Browser
recruitengineers
PRO
12
3.7k
JavaScript 研修
recruitengineers
PRO
8
2.1k
TypeScript入門
recruitengineers
PRO
37
14k
モダンフロントエンド 開発研修
recruitengineers
PRO
13
7.8k
Webアクセシビリティ入門
recruitengineers
PRO
4
2.2k
Other Decks in Business
See All in Business
Gemini と NotebookLM を組み合わせて 目標設定の負荷を軽減する方法 / Goal setting with gemini and notebooklm
tbpgr
20
40k
SRE は管理職に向いている
yoshiiryo1
6
4.7k
enechain company deck_english
enechain
PRO
0
120
Guiding teams, and shaping a portfolio, using Wardley Maps & DDD at KanDDDinsky
marijn
0
110
採用ピッチ資料
mimirin
0
170
CREFIL Inc. / Company Profile
crefil
0
370
Mico_New_graduate_2027.pdf
micoinc
0
110
데이터 분석가 없이 데이터 드리븐 디자인하기 | 2025년 11월 세미나
datarian
0
800
会社紹介資料
gatechnologies
2
130k
BizMowサービス資料紹介
bizmow
0
120
Transparency Report: First Half of 2025
mercari_inc
0
120
マネージャーの「責任」、サーバントリーダーの「精神」 スクラムマスターの「行動」
ichizin
2
130
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.7k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.5k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Raft: Consensus for Rubyists
vanstee
140
7.2k
Stop Working from a Prison Cell
hatefulcrawdad
272
21k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.5k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Become a Pro
speakerdeck
PRO
29
5.6k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
2.9k
Building Adaptive Systems
keathley
44
2.8k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Transcript
@motoshima1150 iOSDC 2023 SwiftUIの進化に ついていくためにやったこと
このセッションのねらい 『スタディサプリ 中学講座』がSwiftUIと共に歩んできた道を振り返りました。 ポイント1 直面した課題の例として 具体的にAlert, NavigationViewの進化を知る SwiftUIのような進化の早いフレームワークと どのように付き合うのかを考える ポイント2
Agenda | 01 02 03 04 発表者紹介 SwiftUIと『スタディサプリ 中学講座』 SwiftUIの実践的な書き換え
まとめ
発表者紹介 01
@motoshima1150 / 中島元成 - iOS アプリエンジニア - 『スタディサプリ 中学講座』開発を担当 -
🍺, 🏕, "3dメガネ アイコン" by DesignBolts is licensed underCC BY 4.0
(株)リクルートでの位置づけ 創業 本社 事業の売上収益 従業員数 2012年 10月1日 株式会社リクルートホールディングス設立時の 分社化により設立 2018年
4月1日 株式会社リクルートに商号変更 東京 7,606億円 (2022年4月1日~2023年3月31日) 19,836人 (2023年4月1日現在 / アルバイト・パート含) OUR VISION
サービスラインナップ 様々なサービスラインナップにて事業展開をしています スタディサプリ 対象学年 小・中学校 高校 大学・社会人 オンラインビデオ (B to
C) オンラインビデオ& アセスメント (B to B to C) オンラインコーチング パーソナルコーチプラン
SwiftUIと『スタディサプリ 中学講座』 02
SwiftUI 年表 と『スタディサプリ 中学講座』 WWDC19 WWDC20 WWDC21 WWDC22 WWDC23 SwiftUI発表
SwiftUIベースのアプリ構築が可能に Listや検索の大幅強化 .searchable modifierの追加 .refreshable modifierの追加 .swipeActions modifierの追加 NavigationStackの追加 Charts フレームワークの追加 Photos フレームワークの追加 KeyframeAnimation @Observable の追加 MapKit の強化 SwiftDataのサポート リニューアルリ リース リニューアル 開始
『スタディサプリ 中学講座』はSwiftUIと共に歩んでいる
どのような課題が発生したか • 既存実装が非推奨となり、将来的に廃止されてしまう ◦ Alert, NavigationLink • 新規APIが公開されるが、対応バージョン要件を満たせず導入できない ◦ NavigationStack
Alert, Navigationのケースで書き換えをご紹介いたします
… 『スタディサプリ 中学講座』の構成 スタディサプリ 中学講座 project Core: 依存関係や共通処理を持つ UIComponent: 共通UIやDesignSystem
の token などを持つ JuniorHighSchool: 実際の画面単位でサブモジュールを用意 MyPage StudyReport … マルチモジュール構成に移行中。各モジュール間は独立した実装が可能になっています。 コラム
SwiftUIの実践的な書き換え 03
@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+
『スタディサプリ 中学講座』でのAlert用途 • ユーザーに向けて通信エラーを伝える • 学習を離脱するなどのユーザー状態が破棄される前の確認 • 強制バージョンアップやメンテナンスなどの強制力の強いユーザー告知
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を付与した際に表示されない動作の 回避として利用
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
『スタディサプリ 中学講座』でのNavigation用途 • Push遷移(2−3階層) • プログラムで制御された Push遷移 • 1画面から複数の種類の遷移先
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が消えてスッキリ
運用状況
1. Issueを作成し、課題としてチーム内共有する。 2. 動作確認の担保、書き換え方針を共有する。 3. 品質改善の時間で実際にコードの書き換えを行う。 計画
• 課題をオープンにすることで、以下のメリットを受けています。 ◦ 目につくので忘れない ◦ いつでも見返せる ◦ 対応時期のコミュニケーションが容易 1. Issueを作成し、課題としてチーム内共有する。
• MagicPodを用いたE2Eテストを導入しています。 ◦ 画面遷移などの書き換えも安心して書き換えができます。 • 書き換えの方針などを事前共有によってチーム内で検証します。 2. 動作確認の担保、書き換え方針を共有する。
私たちのチームでは品質改善に向けた実装時間が確保されています。 • Quality Budget ◦ 2週間に1日品質改善に寄与する issueを消化する日を設けています。 • KAIZEN ◦
小中高プロダクトiOSチームでプロダクトを跨いでペアを組み、 週に1回1時間程度品質改善に当てる。 3. 品質改善の時間で実際にコードの書き換えを行う。
• 『スタディサプリ』は年に1回バージョン更新を行なっています。 ◦ 今年の4月にiOS 14をサポートバージョンから外しました。 ◦ シェア率を参照しながらPdMとすり合わせを行い更新しています。 • これから導入を控えているもの。 今後の予定は
https://developer.apple.com/documentation/swiftui/navigationstack https://developer.apple.com/documentation/swiftui/view/presentationdetents(_:)
まとめ 04
私たちはSwiftUIの進化を追いながら、落ち着いて取捨選択ができたと思います。 書籍「進化的アーキテクチャ」と照らし合わせ要因を振り返りました。 要因 • 年一回のサポートバージョンの見直しタイミングがある ◦ 腐敗防止層の対策が立てやすい • モジュール分割により、新しいコードは新しい設計で書くことができる ◦
漸進的な改善を行うことができる • メインタスクとは別で品質改善のために取り組む時間がある ◦ 心理的にも余裕が生まれる 運用を通しての振り返り
最後に『スタディサプリ 中学講座』で得たまなび 私たちのSwiftUIという選択は、2020年時点では将来性のリスクを取ることだったと思 います。 導入時点ではどれも予測のつかない変化でしたが、その点で過剰に忌避するのでは なく、ワークアラウンドな対応なども受け入れながらSwiftUIの進化に合わせて一緒に 進化しつつ、導入タイミングはプロダクトでハンドリングできる基盤を整えておくことの 重要性を改めてまなぶことができました。
その他 弊社についてのご紹介 以下リンク先でもプロダクト開発部について紹介しています。ぜひご覧ください。 ・スタディサプリ プロダクトチーム ブログ スタディサプリ Product Team Blog 発表資料
- スタディサプリ Product Team Blog ※エンジニア / デザイナー / TPMが記事を書いています ・ブランドサイト スタディサプリ BRAND SITE ・採用ページはこちら キャリア | スタディサプリ BRAND SITE ・カジュアル面談はこちらからお気軽にご応募ください スタディサプリエンジニア職種カジュアル面談エントリーフォーム
一緒に事業拡大を目指す仲間を お待ちしています!
ご清聴ありがとうございました