Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。| iOSDC 2021
Search
nkmrh
September 18, 2021
Programming
6.8k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。| iOSDC 2021
nkmrh
September 18, 2021
Other Decks in Programming
See All in Programming
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
120
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
600
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
290
すこし踏み込む CancellationToken
htkym
1
330
速習iPhone Duo対応
yuukiw00w
1
550
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
350
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
130
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
290
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.1k
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
220
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
140
Featured
See All Featured
Skip the Path - Find Your Career Trail
mkilby
1
230
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Making Projects Easy
brettharned
120
6.8k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
810
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Docker and Python
trallard
47
4.2k
Transcript
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 「スタディサプリ」がFull SwiftUIを選択した 先に見えてきたもの。 Hajime NAKAMURA @_nkmrh iOSDC
Japan 2021
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 @_nkmrh / 中村 肇 ➔ iOS アプリエンジニア
➔ 2020年4月にQuipperに入社 ◆ 新規プロダクト開発 iOS担当 ◆ 小中高大学受験向けスタディサプリの一部運用を担当
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 「Full SwiftUI」 @main struct full_swiftuiApp: App {
var body: some Scene { WindowGroup { ContentView() } } }
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 Full SwiftUI を選択した背景 02
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 新規開発アプリの要件 講座一覧 授業動画 問題演習
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 新規開発アプリの要件 iOS 14 以降 プッシュ通知 App内課金 オンボーディング
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 技術検証 ➔ 想定するデザインのプロトタイプをSwiftUIで実装 ➔ Full SwiftUIでのアーキテクチャパターンの検証 ➔
UIKitを組み合わせる仕組みの検証
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 👀 見えてきたメリット 👍 02
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 アニメーション
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 要件 ➔ ボタンを押してリストに要素を追加/削除し、任意のアニメーションを適用 ◆ 追加時:左から右へスライドイン ◆ 削除時:拡大・縮小
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 追加 削除
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 Button("+1") { withAnimation { appendItem() } }
Button("-1") { withAnimation { removeItem() } } ボタンの実装 withAnimation(_:_:)メソッドのbody 引 数 の中で配列を操作することでアニメーション を適用します
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 List { ForEach(items, id: \.self) { item
in Row(item: item) .transition( AnyTransition.asymmetric( insertion: AnyTransition.slide.combined(with: AnyTransition.opacity), removal: .identity ) ) } } 追加時アニメーション AnyTransition.asymmetric(insertion:removal:)を使う と、Viewの挿入時と削除時で異なる Transitionを適用で きる
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 struct ScaleTransitionEffect: GeometryEffect { var animationFactor: CGFloat
var animatableData: CGFloat { get { animationFactor } set { animationFactor = newValue } } func effectValue(size: CGSize) -> ProjectionTransform { // 次スライドで実装 } } 削除時アニメーション animatableDataプロパティで 値 の 変 化に基づいたアニメーションを提 供す る
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 func effectValue(size: CGSize) -> ProjectionTransform { let
anchorPoint = CGPoint(x: size.width / 2, y: size.height / 2) // 2次関数を利用 `f(x) = ax^2 + bx + c` let scale = quadraticFunction(x: animationFactor, a: -6.8, b: 5.8, c: 1) return ProjectionTransform( CGAffineTransform.identity .translatedBy(x: anchorPoint.x, y: anchorPoint.y) .scaledBy(x: scale, y: scale) .translatedBy(x: -anchorPoint.x, y: -anchorPoint.y) ) } 削除時アニメーション
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 List { ForEach(items, id: \.self) { item
in Row(item: item) .transition( AnyTransition.asymmetric( insertion: AnyTransition.slide.combined(with: AnyTransition.opacity), removal: AnyTransition.modifier( active: ScaleTransitionEffect(animationFactor: 1), identity: ScaleTransitionEffect(animationFactor: 0) ) ) ) } } 削除時アニメーション
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 アニメーションまとめ ➔ withAnimation(_:_:)で変数の変化に合わせてア ニメーションを簡単適用 ➔ .transitionモディファイアでViewの追加/削除時の トランジションを適用
➔ GeometryEffectプロトコルを実装してViewにア フィン変換を適用
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 👀 見えてきたデメリット 😇 03
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 ライブラリの対応 ライフサイクル系メソッドの不安定な動作 ➔ Firebase の自動スクリーントラッキングが対応していない ◆ (firebase-ios-sdk
v8.2.0) ➔ onAppear()が予期しないタイミングで呼ばれる ◆ TabViewで非表示タブのView.onAppearが呼ばれたりする
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 class ViewModel: ObservableObject { @Published var isPresented
= false { didSet { if isPresented { logger?.screenEvent("second_screen") } else { logger?.screenEvent("first_screen") } } } ... } struct FirstScreen: View { @StateObject var viewModel = ViewModel() var body: some View { NavigationLink( destination: SecondScreen(), isActive: $viewModel.isPresented, label: { EmptyView() } ) ... } } スクリーントラッキングログ実装例
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 ➔ Firebaseの自動スクリーントラッキングログはSwiftUI未対応 ◆ (firebase-ios-sdk v8.2.0) ➔ Viewのライフサイクル系メソッドの挙動が不安定
◆ .onAppear() 見えてきたデメリットまとめ
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 👀 見えてきたtips 04
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 プログラムで画面遷移を制御する
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 APIと通信して条件に適した場合のみ、 一覧画面から詳細画面へプッシュ遷移したい 要件
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 基本のPush遷移実装 *https://developer.apple.com/tutorials/app-dev-training/creating-a-navigation-hierarchy private let items = ["Apple",
"Banana", "Cat", "Dog"] var body: some View { List { ForEach(items, id: \.self) { item in NavigationLink( destination: Text(item) ) { Text(item) } } } NavigationLinkと遷移先のView を設定するだけで完成
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 プログラムで画面遷移を制御したい ➔ チュートリアルのコードでは、ユーザーのタップ入力を受ける前提なので、プ ログラムでの遷移には使えない ➔ 通信が完了したら遷移する処理を実装するには、NavigationLinkの isActive引数を取るInitializer*を使う
*https://developer.apple.com/documentation/swiftui/navigationlink/init(_:isactive:destination:)-6xw7h
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 @State private var isSelected = false var
body: some View { ZStack { Button(action: { // 通信を行う模擬実装 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { isSelected = true } }) { Text("Submit") } プログラムでの画面遷移方法 isActiveフラグのBinding先を定義 非同期処理が終わるとフラグをtrueに変更
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 @State private var isSelected = false var
body: some View { ZStack { NavigationLink( destination: Text(item), isActive: $isSelected) { EmptyView() } Button(action: { … } プログラムでの画面遷移方法 NavigationLinkを 設 置 して、isActiveフラグを isSelectedのStateにBindingさせる
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 struct Selection<T> { var isSelected: Bool var
item: T? { didSet { isSelected = item != nil } } … } 一覧画面から詳細画面への遷移 Selection ➔ 一覧画面で選択したアイテムを保持 ➔ 画面遷移のトリガー isActiveフラグのBinding先として定義 アイテムをセットしてフラグを更新
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 Itemを選択すると遷移する隠しNavigationLinkを作成 Selectionを使った画面遷移 @State private var selection =
Selection<String>(item: nil) @ViewBuilder private var navigationLinkIfPossible: some View { if let selectedItem = selection.item { NavigationLink( destination: Text(selectedItem), isActive: $selection.isSelected) { EmptyView() } } else { EmptyView() ... フラグが必ずtrueになるので自動的に遷移する アイテムがあった場合のみ、NavigationLinkを生成する
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 var body: some View { ZStack {
navigationLinkIfPossible List { ForEach(items, id: \.self) { item in Button(action: { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { selection = .init(item: item) } }) { Text("\(item)") } ... アイテムをセットして遷移をトリガー 隠しNavigationLinkを設置 非同期処理完了後、アイテムをセット
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 APIと通信して条件に適した場合のみ、 一覧画面から詳細画面へプッシュ遷移したい ➔ 隠しNavigationLinkとSelectionを組み合わせて実装 NavigationLinkをプログラムで制御するまとめ
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 Full SwiftUI で開発した所感 05
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 Full SwiftUI で開発した所感 ➔ UIの実装がスピードアップ ◆ レイアウトの記述がシンプル
◆ ライブプレビューで素早く動作確認が可能 ➔ 実装の変更やレビューがしやすい ➔ 開発体験が加速!🚀 ➔ ⚠ 今回紹介した事例の他、ハマりポイントや懸念はあるのでそこ は強いやっていき💪が必要
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 https://quipper.hatenablog.com/archive/category/Engineering-Native-iOS ➔ 「スタディサプリ」が React Native から卒業するまで、ある いは技術的負債への感謝と敬意
➔ iOS アプリ開発とユニットテスト ➔ iOS/Androidチーム合同でユニットテストクロスレビューを 行っている話 ➔ SwiftUIのディープリンク対応:プッシュ通知から画面遷移 する方法 本日お伝えした詳細や他のトピックを投稿しています!
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 選考・採用イベント ご応募方法 リクルートは仲間を積極募集中です!!! このページをご覧の方限定の特設応募サイトよりご登録ください 採用イベント カジュアル面談 まずは気
軽にカジュアルに話を してみたい 選考受験 スピーディーに選考でこれまでの 経験が活かせるか確認したい
#iosdc 「スタディサプリ」がFull SwiftUIを選択した先に見えてきたもの。 ご清聴ありがとうございました