旧 NavigationView との違い
iOS 16 で NavigationStack と NavigationSplitView が導入され、従来の NavigationView は非推奨になりました。両者の違いと移行のポイントを解説します。
基本的な置き換え
// 旧: NavigationView
NavigationView {
List {
NavigationLink("詳細") {
DetailView()
}
}
}
// 新: NavigationStack
NavigationStack {
List {
NavigationLink("詳細") {
DetailView()
}
}
}シンプルなケースでは、NavigationView を NavigationStack に置き換えるだけで動作します。
主な違い
プログラム的なナビゲーション
NavigationStack は path パラメータでナビゲーション履歴を制御できる。NavigationView ではこれが困難だった。
値ベースの遷移
NavigationStack では navigationDestination で型に基づいた遷移先を定義できる。コードの見通しが良くなる。
iPad/Mac 対応
NavigationView の .columns スタイルは NavigationSplitView に分離された。役割が明確になった。
NavigationLink の変化
// 旧: isActive バインディング
@State private var isActive = false
NavigationLink(isActive: $isActive) {
DetailView()
} label: {
Text("詳細")
}
// 新: 値ベースのナビゲーション
@State private var path = NavigationPath()
NavigationStack(path: $path) {
Button("詳細") {
path.append("detail")
}
.navigationDestination(for: String.self) { value in
DetailView()
}
}スタイル指定の変化
// 旧: NavigationView + navigationViewStyle
NavigationView {
/* ... */
}
.navigationViewStyle(.columns)
// 新: NavigationSplitView を使用
NavigationSplitView {
/* サイドバー */
} detail: {
/* 詳細 */
}NavigationView + .stack
NavigationStack で置き換え。スタック型のナビゲーション。
NavigationView + .columns
NavigationSplitView で置き換え。マルチカラムレイアウト。
移行時の注意点
| 旧 API | 新 API |
|---|---|
| NavigationView | NavigationStack または NavigationSplitView |
| NavigationLink(isActive:) | NavigationLink(value:) + navigationDestination |
| NavigationLink(tag:selection:) | NavigationLink(value:) + path |
| .navigationViewStyle(.stack) | NavigationStack |
| .navigationViewStyle(.columns) | NavigationSplitView |
後方互換性
iOS 15 以前もサポートする必要がある場合は、条件分岐で対応します。
struct ContentView: View {
var body: some View {
if #available(iOS 16.0, *) {
NavigationStack {
MainList()
}
} else {
NavigationView {
MainList()
}
.navigationViewStyle(.stack)
}
}
}移行のメリット
// NavigationStack の利点: ディープリンクが簡単
struct ContentView: View {
@State private var path: [Route] = []
var body: some View {
NavigationStack(path: $path) {
HomeView()
.navigationDestination(for: Route.self) { route in
destinationView(for: route)
}
}
.onOpenURL { url in
// URL から path を構築してディープリンク
if let route = parseURL(url) {
path = [route]
}
}
}
}NavigationView では実現が難しかったプログラム的なナビゲーション制御が、NavigationStack では自然に書けるようになりました。新規プロジェクトでは必ず NavigationStack / NavigationSplitView を使用しましょう。