Slide 1

Slide 1 text

SwiftUIのハマりどころと その回避策 株式会社リクルート ⼤塚 悠貴 2022/9

Slide 2

Slide 2 text

はじめに © Recruit Co., Ltd. All Rights Reserved 2

Slide 3

Slide 3 text

3 ⾃⼰紹介 © Recruit Co., Ltd. All Rights Reserved ⼤塚 悠貴 (@moguaiyuki) 所属 経歴 株式会社 リクルート 2020年 4⽉ 株式会社リクルート新卒⼊社 2020年 7⽉ ゼクシィiOS開発 2020年 10⽉ 新規事業プロダクトオーナー 2021年 10⽉ iOS開発

Slide 4

Slide 4 text

4 本トークのゴール iOS14以上を対象とした『Airインボイス』iOSアプリにおいて SwiftUIを⽤いてさまざまな要件を実現するにあたり、 はまったポイントやそれらをどのように回避したか を共有することで SwiftUIの採⽤の⼀助となる © Recruit Co., Ltd. All Rights Reserved

Slide 5

Slide 5 text

『Airインボイス』とは © Recruit Co., Ltd. All Rights Reserved 5

Slide 6

Slide 6 text

Airインボイスとは © Recruit Co., Ltd. All Rights Reserved 6 リクルートの事業内容について(主なサービス) 4 選択・意思決定を⽀援する情報サービスを提供し、 「まだ、ここにない、出会い。より速く、シンプルに、もっと近くに」を実現する マッチング&ソリューションSBU HRテクノロジーSBU ⼈材派遣SBU 国内派遣 海外派遣

Slide 7

Slide 7 text

https://recruit-holdings.com/files/ir/ir_news/upload/20220712_ps_jp.pdf リリース⽇変える Air Business Toolsのいい感じの図持ってきて、 その中のInvoiceって⽴ち位置を説明する https://recruit-holdings.com/files/ir/ir_news/upload/20220712_ps_jp.pdf

Slide 8

Slide 8 text

8 ※①調査主体︓株式会社リクルート②調査実施機関︓株式会社インテージ(2021年11⽉22⽇時点) ③⽐較条件︓銀⾏133⾏(*)の通常時の他⾏宛の 振込⼿数料で⽐較(条件付きの振込⼿数料は考慮せず) (*)⾦融庁、免許・許可・登録等を受けている業者⼀覧のうち、預⾦取扱等⾦融機関で銀⾏として登録されているもの。外国銀⾏⽀店を除く133⾏

Slide 9

Slide 9 text

9 『Airインボイス』 とは

Slide 10

Slide 10 text

『Airインボイス』 における SwiftUI採⽤の背景とその効果 © Recruit Co., Ltd. All Rights Reserved 10

Slide 11

Slide 11 text

11 SwiftUI採⽤の背景とその効果 © Recruit Co., Ltd. All Rights Reserved • 新規開発 (既存コードなし) • SwiftUIが安定してきたiOS14以上をサポート • 社内でもスタディサプリが既にSwiftUI採⽤済み SwiftUIの採⽤背景 • UIの実装速度が向上 • レイアウトの記述がシンプル • コンポーネントの再利⽤が容易 • Previewで⾼速にUI変更確認 • Storyboardやxibと⽐較してレビューが容易 …など、メリットを沢⼭感じることができた SwiftUI採⽤による効果

Slide 12

Slide 12 text

ハマりどころとその回避策 © Recruit Co., Ltd. All Rights Reserved 12 ※本スライドはiOS14, 15をサポート対象とする前提のコードとなっています。

Slide 13

Slide 13 text

13 様々な要件 1. DeepLink 2. 1画⾯で複数種類のアラートダイアログ 3. 1画⾯から複数の画⾯へのモーダル遷移 4. カスタムダイアログ / トースト / チュートリアル © Recruit Co., Ltd. All Rights Reserved

Slide 14

Slide 14 text

14 様々な要件 1. DeepLink 2. 1画⾯で複数種類のアラートダイアログ 3. 1画⾯から複数の画⾯へのモーダル遷移 4. カスタムダイアログ / トースト / チュートリアル © Recruit Co., Ltd. All Rights Reserved

Slide 15

Slide 15 text

15 SwiftUIでの基本的なpush遷移 © Recruit Co., Ltd. All Rights Reserved ユーザーがNavigationLinkを タップすることで遷移 Deep linkのようなプログラム的に遷移する要件には使えない

Slide 16

Slide 16 text

16 プログラムで遷移を制御する © Recruit Co., Ltd. All Rights Reserved ※iOS16以上ではinit(value: label:)を使⽤ 空(EmptyView)のNavigationLinkを Backgroundに仕込む destinationの値が”pageA”になった時 遷移を発⽕する

Slide 17

Slide 17 text

17 アプリのどこからでも遷移を制御できるようにする © Recruit Co., Ltd. All Rights Reserved @EnvironmentObjectにViewRouterを格納し、 アプリのどこからでも遷移を制御できるようにする 各画⾯の画⾯遷移を制御するViewRouterをまとめた ObservableObject 遷移先を定義 viewRouter.firstPageViewRouter.destinationの 値を変更することで遷移を発⽕する

Slide 18

Slide 18 text

18 DeepLinkを実装する © Recruit Co., Ltd. All Rights Reserved .onOpenURLでURLスキームを 受け取り、ViewRouterを⽤いて 画⾯遷移を発⽕する

Slide 19

Slide 19 text

ハマりポイント① © Recruit Co., Ltd. All Rights Reserved 19

Slide 20

Slide 20 text

20 このコードどこに問題があるでしょうか︖

Slide 21

Slide 21 text

21 このコードどこに問題があるでしょうか︖ NavigationLinkが2つあることが問題 ※ iOS15は問題なし

Slide 22

Slide 22 text

22 iOS14&NavigationLink 2つのみの場合挙動が不安定 © Recruit Co., Ltd. All Rights Reserved ページ3まで遷移すると 勝⼿にページ1に戻る ページ1 ページ2 ページ3 遷移 遷移 ※デモ動画

Slide 23

Slide 23 text

23 iOS14系&NavigationLink 2つのみの場合挙動が不安定 © Recruit Co., Ltd. All Rights Reserved 遷移直後に勝⼿に戻る問題の報告 NavigationLinkが 2つの場合のみ発⽣ https://developer.apple.com/forums/thread/677333 https://forums.swift.org/t/14-5-beta3-navigationlink-unexpected-pop/45279

Slide 24

Slide 24 text

24 回避策 © Recruit Co., Ltd. All Rights Reserved ダミーのNavigationLinkをいれて NavigationLinkの数を3つにする

Slide 25

Slide 25 text

ハマりポイント② © Recruit Co., Ltd. All Rights Reserved 25

Slide 26

Slide 26 text

26 このコードどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved 特定のボタンがタップされた際に、そのボタンに応じた値を遷移先に渡したい ボタンがタップされたら pageAIdを代⼊する pageAIdがあるときのみ、 NavigationLinkを⽣成する

Slide 27

Slide 27 text

27 このコードどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved NavigationLinkを⽣成した直後に 遷移を発⽕していることが問題

Slide 28

Slide 28 text

28 if letでNavigationLinkが⽣成された直後に遷移すると 遷移アニメーションがなくなる(iOS14&15) © Recruit Co., Ltd. All Rights Reserved 期待動作 実際 ※デモ動画 ※デモ動画

Slide 29

Slide 29 text

29 回避策? © Recruit Co., Ltd. All Rights Reserved この遷移を使う時は必ずpageAIdがnon-null 強制アンラップしてみる︖

Slide 30

Slide 30 text

30 回避策? © Recruit Co., Ltd. All Rights Reserved この遷移を使う時は必ずpageAIdがnon-null 強制アンラップしてみる︖ Viewを⽣成した時点ではnullなのでもちろんダメ

Slide 31

Slide 31 text

31 回避策 © Recruit Co., Ltd. All Rights Reserved destinationの中でif letを使⽤する

Slide 32

Slide 32 text

32 様々な要件 1. DeepLink 2. 1画⾯で複数種類のアラートダイアログ 3. 1画⾯から複数の画⾯へのモーダル遷移 4. カスタムダイアログ / トースト / チュートリアル © Recruit Co., Ltd. All Rights Reserved

Slide 33

Slide 33 text

33 1画⾯で複数種類のアラートダイアログを表出する © Recruit Co., Ltd. All Rights Reserved

Slide 34

Slide 34 text

ハマりポイント③ © Recruit Co., Ltd. All Rights Reserved 34

Slide 35

Slide 35 text

35 このコードのどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved

Slide 36

Slide 36 text

36 このコードのどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved 1つのViewに対して複数の.alertを 利⽤していることが問題 ※ iOS14 15共に問題あり

Slide 37

Slide 37 text

37 1つのViewに対して1つしか.alertは定義できない © Recruit Co., Ltd. All Rights Reserved 2つ⽬の.alertのみ有効

Slide 38

Slide 38 text

38 2つ⽬のアラートしか表⽰されない © Recruit Co., Ltd. All Rights Reserved アラート1は表⽰されない アラート2は表⽰される

Slide 39

Slide 39 text

39 回避策 © Recruit Co., Ltd. All Rights Reserved 1つの.alertの中で 複数パターン出し分ける アラートのパターンを定義しておく

Slide 40

Slide 40 text

40 様々な要件 1. DeepLink 2. 1画⾯で複数種類のアラートダイアログ 3. 1画⾯から複数の画⾯へのモーダル遷移 4. カスタムダイアログ / トースト / チュートリアル © Recruit Co., Ltd. All Rights Reserved

Slide 41

Slide 41 text

41 ある画⾯から⼆つの画⾯にモーダル遷移したい © Recruit Co., Ltd. All Rights Reserved

Slide 42

Slide 42 text

ハマりポイント④ © Recruit Co., Ltd. All Rights Reserved 42

Slide 43

Slide 43 text

43 このコードのどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved

Slide 44

Slide 44 text

44 このコードのどこに問題があるでしょうか︖ © Recruit Co., Ltd. All Rights Reserved 1つのViewに対して 2つの.fullScreenCoverを 利⽤していることが問題 ※iOS14.5以上は問題ない

Slide 45

Slide 45 text

45 iOS14.5未満では.fullScreenCoverは 1つのViewに対して2つ使えない © Recruit Co., Ltd. All Rights Reserved ページ1に遷移しない ページ2には遷移する

Slide 46

Slide 46 text

46 回避策(?) © Recruit Co., Ltd. All Rights Reserved 1つのEmptyViewに対して1つの .fullScreenCoverを定義する

Slide 47

Slide 47 text

47 iOS14(iOS14.5含む)で正常に動作する © Recruit Co., Ltd. All Rights Reserved ページ1に遷移 ページ2に遷移

Slide 48

Slide 48 text

48 iOS15でどちらも動かない © Recruit Co., Ltd. All Rights Reserved ページ1に遷移しない ページ2に遷移しない

Slide 49

Slide 49 text

49 苦⾁の回避策 © Recruit Co., Ltd. All Rights Reserved iOS14.5未満かどうかで 実装を変更 条件によってmodifierを適⽤する modifier

Slide 50

Slide 50 text

50 様々な要件 1. DeepLink 2. 1画⾯で複数種類のアラートダイアログ 3. 1画⾯から複数の画⾯へのモーダル遷移 4. カスタムダイアログ / トースト / チュートリアル © Recruit Co., Ltd. All Rights Reserved

Slide 51

Slide 51 text

51 TabViewやNavigationViewを含む 全画⾯に対してカスタムUIを被せる © Recruit Co., Ltd. All Rights Reserved

Slide 52

Slide 52 text

ハマりポイント⑤ © Recruit Co., Ltd. All Rights Reserved 52

Slide 53

Slide 53 text

53 NavigationViewやTabViewの⼦Viewに対して カスタムダイアログを表⽰すると全画⾯に被さらない © Recruit Co., Ltd. All Rights Reserved ⼦Viewでダイアログを 管理する

Slide 54

Slide 54 text

54 NavigationViewに対してカスタムダイアログを表⽰すれば 実現可能だが、ダイアログ等は各タブや遷移先で管理したい © Recruit Co., Ltd. All Rights Reserved NavigationViewに対して カスタムダイアログを宣⾔する TabViewA内でshowDialog変数を Trueにしてダイアログを表⽰する

Slide 55

Slide 55 text

55 UIWindowを活⽤する © Recruit Co., Ltd. All Rights Reserved 全画⾯に表⽰したいカスタムUIは全て UIWindowを⽤いて実装

Slide 56

Slide 56 text

56 UIWindowを活⽤する © Recruit Co., Ltd. All Rights Reserved どのViewからでも全画⾯の ダイアログが表⽰可能

Slide 57

Slide 57 text

57 UIWindowを利⽤することで、カスタムダイアログ の上にさらにチュートリアルを出すことも © Recruit Co., Ltd. All Rights Reserved チュートリアルとカスタムダイアログを別々の Windowで管理しているため、簡単に実現可能

Slide 58

Slide 58 text

まとめ © Recruit Co., Ltd. All Rights Reserved 58

Slide 59

Slide 59 text

59 まとめ © Recruit Co., Ltd. All Rights Reserved ①iOS14系のNavigationLinkの挙動には気をつける ②If let でNavigationLinkは⽣成しない ③.alertは1つのViewに対して1つのみ ④.fullScreenCoverはiOS14.5未満に対しては1つのViewに1つのみ ⑤全画⾯にまたがるカスタムダイアログ等はUIWindowの活⽤も⼀つの選択肢 ハマりポイント

Slide 60

Slide 60 text

60 まとめ © Recruit Co., Ltd. All Rights Reserved UIの実装速度が向上 l レイアウトの記述がシンプル l コンポーネントの再利⽤が容易 l Previewで⾼速にUI変更確認 l Storyboardやxibと⽐較してレビューが容易 ….など、メリットを沢⼭感じることができた SwiftUIはハマりポイントもあったが、総じて採⽤してよかった 採⽤してよかった理由