SwiftUI 中的导航视图:NavigationLink、navigationDestination、NavigationView、NavigationStack 和 NavigationSplitView 比较与示例

在 SwiftUI 中,有多种方式可以实现视图之间的导航。本文将比较 NavigationLinknavigationDestinationNavigationViewNavigationStackNavigationSplitView 的用法和特点,并提供示例代码。

NavigationLink 是最常用的导航方式,适用于简单直接的导航场景,如列表中导航到详情页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import SwiftUI

struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Home View")
NavigationLink(destination: DetailView()) {
Text("Go to Detail View")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
.navigationTitle("Home")
}
}
}

struct DetailView: View {
var body: some View {
Text("Detail View")
.navigationTitle("Detail")
}
}

navigationDestination 是 iOS 16 引入的,用于处理更复杂的导航逻辑,允许基于数据或路径动态决定要显示的目标视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import SwiftUI

struct ContentView: View {
@State private var selectedItem: String?

var body: some View {
NavigationStack {
VStack {
Text("Home View")
Button("Go to Item 1") {
selectedItem = "Item 1"
}
Button("Go to Item 2") {
selectedItem = "Item 2"
}
}
.navigationDestination(for: String.self) { item in
DetailView(itemName: item)
}
.navigationTitle("Home")
}
}
}

struct DetailView: View {
var itemName: String

var body: some View {
Text("Detail View for \(itemName)")
.navigationTitle(itemName)
}
}

NavigationView 是 SwiftUI 最早的导航容器,适用于简单的层级导航结构。而 NavigationStack 是 iOS 16 引入的,提供了更灵活的导航路径管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import SwiftUI

struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
Text("Home View")
NavigationLink(destination: DetailView()) {
Text("Go to Detail View")
}
}
.navigationTitle("Home")
}
}
}

NavigationSplitView 是 iOS 16 和 macOS 上引入的,用于支持复杂的分栏式布局,类似于 UISplitViewController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import SwiftUI

struct ContentView: View {
var body: some View {
NavigationSplitView {
SidebarView()
} detail: {
DetailView()
}
}
}

struct SidebarView: View {
var body: some View {
List {
NavigationLink("Item 1", destination: DetailView(item: "Item 1"))
NavigationLink("Item 2", destination: DetailView(item: "Item 2"))
}
.navigationTitle("Sidebar")
}
}

struct DetailView: View {
var item: String?

var body: some View {
if let item = item {
Text("Detail for \(item)")
} else {
Text("No Item Selected")
}
}
}

NavigationSplitView 可以自动适配不同设备,如 macOS、iPad 和 iPhone,提供统一的导航体验。