STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

NavigationView -> NavigationStackにしてみた話

Intro

こんにちは!STORES株式会社STORESレジの開発メンバーAdamです!最近 後夜祭 iOSDC 2023で発表した「NavigationView -> NavigationStackにしてみた話」のブログです!見逃した人ぜひ読んでみてね〜

背景

レジアプリがiOS16のみでNavigationViewを使っている・特定の動作でクラッシュ(OUTLINED_FUNCTION_X)するケースがありました。 調べていたところでNavigationStackに置き換えたら起きなくなる

今までのSwiftUI Navigation

今までのSwiftUI Navigationが大まかに3つの方法はあると思います。

  1. SwiftUIのビューをUIHostingControllerに入れてUIKitのNavigationを使う
  2. 古い各ビューで実装する(Deprecatedとなった)SwiftUI Navigationを使う
  3. Router的なものを作ってそこでNavigationを統一する

レジアプリがSwiftUI 1.0から作られているアプリと「良くても悪くてもSwiftUIで頑張る!」って感じだったのでSwiftUIのNavigationを使っている。 最初からSwiftUIで作っているアプリわざわざUIKit入れるのがちょっと違和感を感じました。使ったことある人次のコードみたことあるかな〜

Examples

Root Destination
Modal
Push

上記は各ビューに実装する形になるけどもし複雑な遷移した場合, どうやってRootView以外のところでDismissする?ModalだけとじるなどのUIKitで簡単にできるところどうやって実現する?

...

...

...

はい、SwiftUIで頑張るって言ったばかりだけどUIKit使ってしまっている。やっぱりまだ物足りないところあります。。。 普通にUIKitそのまま使ってしまっていた理由:

  1. DismissFrontViewControllerの場合
    1. 一画面のModalをDismissする時だけは使う必要ない
    2. SwiftUIだとModalで別の画面に遷移した場合は簡単にModal閉じれない
  2. PopToRootも似ているような問題で複数のViewを一気にdismissしたい場合は大変になる(StackのDepthによって何回dismissするべきか)

Navigation Stackについて

iOS 16から二つの新しいNavigationが追加されていました。NavigationStack・NavigationSplitView

今回はNavigationStackのみに集中します

NavigationStack周りで二つの新しいところを紹介したいです。 まずはpresentedItems、こちらは現状のStackのステートをコントロール・トラックできるようになっている 自動的にこの配列がビューが追加・削除でアップデートされるし、自分でもProgramattically追加・削除できる これは嬉しい変更ですね

二つ目はこちらのNavigationLinkの新しいInitializer. init(title:value:) DeprecatedのAPI使っている場合だとpresentedItemsがアプデートされないので注意 Setで考えてもらえれば

NavigationView -> NavigationStackにしてみた

単純にNavigationView -> NavigationStackに置き換えてみました!

今まで通りNavigationView置く場所に代わりにおいたら完了!

意外とそのままいけた!。。。と思っていたら上に紹介したWorkaroundのところがぶっ壊れてた。。。 PopToRootが今まで通りに動いてくれたけどDismissFrontViewControllerが動かない dismissされるはずの画面がそのままになってしまう

レジチーム残っている課題・これからの方針

紹介したばっかりの対応が先のDismiss動くなくなった問題・iOS 16.4+でクラッシュ修正された理由で急ぐ必要無くなりました。 *最近Crashlyticsチェックしたらまだ起きているけど頻度はとても少ない 😇

その古い(Deprecatedとなった)SwiftUI Navigationを使うとワークアラウンドが技術負債になっているため解消したい! 次のナビゲーション考えた時にRouterで作ってみたいと思っている iOS 16まで切れたら新しいStackベースに参考して作り直す計画中

まだ設計中・どうなるかわからないけどイメージは 参考: https://blorenzop.medium.com/routing-navigation-in-swiftui-f1f8ff818937

後夜祭の宣伝

10月31日(火) 19:00~、DroidKaigi 2023に協賛しているWED株式会社さん、GO株式会社さん、株式会社ヤプリさん、とアフターイベントを開催します!ぜひご参加ください〜!

また、 STORES ではモバイルエンジニアを募集しています! 少しでも STORES に興味を持たれた方は、ぜひカジュアル面談やBeer Bashに来ていただけると嬉しいです。 (Beer Bashは STORES のオフィスで美味しいお酒を飲み、美味しいごはんを食べながら雑談するだけの会です)