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
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
1
220
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
500
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
3.9k
Simple Storage Service(S3) is not simple
iwatsukayura
0
290
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
400
ActionController meets Protocol Buffers
sorah
0
560
気持ちぃ〜角丸 Squircle
ryu1013
0
320
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
220
Featured
See All Featured
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
330
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.4k
Technical Leadership for Architectural Decision Making
baasie
3
600
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
What does AI have to do with Human Rights?
axbom
PRO
1
2.5k
Odyssey Design
rkendrick25
PRO
2
880
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
640
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.8k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
480
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を選択した先に見えてきたもの。 ご清聴ありがとうございました