
WWDC22 でパワーアップした SwiftUI の Navigation
こんにちは、Zaim で iOS 開発を担当している @ugoです。
WWDC22 では今年も SwiftUI にまつわるさまざまな発表がありましたね。
Apple 純正のグラフライブラリの Charts の発表が話題を集めている一方で、SwiftUI の Navigation にも大きなアップデートがありました!
以下のセッションで新しく発表された SwiftUI の NavigationStack について詳しく紹介されており、従来の Navigationと比較しながら実際に触ってみた感想を共有します。
フラグの管理が必要だった従来の Navigation

セッションの導入でも触れられていた通り、従来の SwiftUI では NavigationView の中で NavigationLink を使用して画面遷移先を指定する必要がありました。
NavigationView {
NavigationLink(destination: SecondView()) {
Text(“Tap”)
}
}
上記のコードでは ”Tap” を押すと SecondView にPush 遷移するようになっています。
通信処理が終わってから遷移するなどの動的な遷移の場合は下記のように NavigationLink の isActive に Binding<Bool> を渡して通信の処理が終わり次第 isActive のフラグを変更することで実現していました。
@State private var isActive = false
NavigationView {
NavigationLink(
destination:SecondView(),
isActive: $isActive,
label: {
Button(action: {
// 通信処理など
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
isActive = true
}
}) {
Text("Tap”)
}
}
)
}
しかし今回の WWDC22 で isActive を引数に取る NavigationLink は deplicatedになりました。

そこで新たに発表されたNavigationStackの登場です!
動的な遷移が実装しやすくなった NavigationStack
SwiftUI の新しい Navigation では NavigationView ではなく NavigationStack で全体を囲います。
NavigationStack に Binding で path を渡すことでスタックに表示されているデータを追跡するようになります。
初期状態の path は空なのでスクリーンショットの画面はホームを表示しています。

NavigationLink では表示するラベルと value に使用するデータを引数として渡します。
遷移先の Deastination は渡さなくなり、代わりに navigationDestination モディファイアに受け取るデータの型と遷移先を指定するようになりました。

NavigationLink をタップすることで value の recipe が path に追加されて遷移先をマッピングしてくれる仕組みになっているようです。

また動的な遷移やホームまで戻る処理も path へのデータの代入や初期化することで実現できます。
従来の SwiftUI ですとホームまで戻る処理は少し工夫しないといけなかったので、とても使いやすくなりました!
また、同じ画面から詳細とは別の画面に別のデータ型を使用して遷移するケースもありますよね。
その場合は navigationDestination モディファイアを複数定義して NavigationStack の path へNavigationPath を渡すことで実現できました!
セッションではView 側で path を定義していましたが、実際のコードでは別の Model に定義して管理すると良さそうですね。
最後に
遷移周りが弱いと言われていた SwiftUI も、今回のアップデートで使いやすくなったのではないでしょうか!
Zaim でも ICカードリーダー を SwiftUI で開発しているので NavigationStack への移行でまた何か知見が得られましたら共有します。
また間違ったことを書いていたらコメントで指摘いただけますと幸いです。
Zaim ではエンジニアを募集しています。ぜひお話を聞きにきてください!