Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftUIのハマりどころとその回避策/ iOSDC_otsuka

Recruit
PRO
September 12, 2022

SwiftUIのハマりどころとその回避策/ iOSDC_otsuka

2022/09/11_iOSDC Japan 2022での、大塚の講演資料になります

Recruit
PRO

September 12, 2022
Tweet

More Decks by Recruit

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. 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

    View Slide

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

    View Slide

  9. 9
    『Airインボイス』 とは

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  23. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide