NavigationView — 一个 SwiftUI 容器组件,用于组织屏幕之间的堆栈导航。NavigationView 创建带有自动导航栏、标题和「返回」按钮的导航堆栈。从 iOS 16 开始,Apple 建议使用 NavigationStack。更多内容请阅读 Apple 文档。
要点
NavigationView — 一个 SwiftUI 容器,它包裹屏幕层次结构并提供导航界面。在 NavigationView 内部运行着 NavigationLink——一个点击后会用新屏幕替换当前屏幕的元素。NavigationView 自动添加带有标题和「返回」按钮的导航栏。
NavigationView 与 SwiftUI 一起在 iOS 13 中出现。从概念上讲,它取代了 UIKit 中的 UINavigationController,但以声明方式实现。开发人员通过 NavigationLink 描述屏幕之间的连接,而不是手动 push/pop。系统自动管理堆栈。
NavigationView 支持 .navigationTitle、.navigationBarTitleDisplayMode、.toolbar 和 .searchable 修饰符。对于 iOS 16+,Apple 引入了 NavigationStack,它保留了 NavigationView 的 API,但通过 NavigationPath 增加了程序化堆栈管理。对于支持 iOS 15 及更早版本的项目,NavigationView 仍然是唯一的选择。
NavigationLink — 一个 SwiftUI 元素,在 NavigationView 或 NavigationStack 内创建到目标屏幕的跳转。点击 NavigationLink 后,系统将目标屏幕添加到导航堆栈。跳转动画——iOS 标准从右侧 push,根据平台进行调整。
struct ContentView: View {
var body: some View {
NavigationView {
List(items) { item in
NavigationLink(destination: DetailView(item: item)) {
Text(item.title)
}
}
.navigationTitle("列表")
}
}
}
struct DetailView: View {
let item: Item
var body: some View {
VStack {
Text(item.description)
.navigationTitle(item.title)
.navigationBarTitleDisplayMode(.inline)
}
}
}NavigationLink 接受两个参数:destination — 目标 View,和 label — 用户点击的元素。对于列表,使用 value 和 NavigationLink(value:) 的语法很方便,它会自动取消选择单元格并与 NavigationPath 配合使用。
从 iOS 16 开始,Apple 推出了 NavigationStack 作为 NavigationView 的替代品。NavigationStack 保留了声明式语法,但增加了一个关键能力——通过 NavigationPath 类型的 path 属性或 Hashable 数组进行程序化堆栈管理。
| 功能 | NavigationView (iOS 13-15) | NavigationStack (iOS 16+) |
|---|---|---|
| 程序化 push | 无,仅通过 NavigationLink | 有,通过 path.append(value) |
| popToRoot | 仅 dismiss 到 root | path.removeLast(path.count) |
| 深层链接 | 实现复杂 | 通过 path 内置支持 |
| 堆栈类型化 | 无(destination 中任意 View) | 有(Hashable 值数组) |
| iPad SplitView | ColumnStyle / StackStyle | NavigationSplitView (iOS 16+) |
对于最低版本为 iOS 16+ 的项目,使用 NavigationStack。对于支持 iOS 14-15 的项目——使用 NavigationView。NavigationStack 没有适用于旧版本的直接替代品,因此升级需要检查兼容性。
.toolbar 和 .navigationTitle 修饰符管理导航栏的内容。.navigationTitle 设置屏幕标题,.navigationBarTitleDisplayMode 选择样式:.large(大标题,默认)或 .inline(紧凑型,如设置应用中)。.toolbar 添加按钮、搜索和分段控制。
struct SettingsView: View {
var body: some View {
NavigationStack {
Form {
Section("个人资料") {
Text("用户名")
Toggle("通知", isOn: $notifications)
}
}
.navigationTitle("设置")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("保存") { save() }
}
ToolbarItem(placement: .navigationBarLeading) {
EditButton()
}
}
}
}
}.searchable — 另一个将搜索栏集成到导航栏的修饰符。可与 NavigationView 和 NavigationStack 配合使用。搜索在滚动时自动隐藏,向下滑动时显示。支持通过 Binding String 进行列表过滤。
NavigationPath — iOS 16+ 的类型,将导航堆栈表示为 Hashable 值的集合。开发人员向 path 添加元素以进行程序化跳转,删除元素以返回。NavigationPath 支持深层链接、推送通知和状态恢复。
struct AppNavigation: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List(categories) { category in
NavigationLink("分类 \(category.name)",
value: category)
}
.navigationTitle("分类")
.navigationDestination(for: Category.self) { category in
ProductListView(category: category)
}
.navigationDestination(for: Product.self) { product in
ProductDetailView(product: product)
}
}
// 通过深层链接的程序化跳转
.onOpenURL { url in
guard let productId = DeepLinkParser.parse(url) else { return }
path.append(Product(id: productId))
}
}
}.navigationDestination(for:) 注册需要显示屏幕的数据类型。当该类型的值添加到 path 时,系统会自动创建目标 View。这种方法取代了显式的 NavigationLink(destination:),使导航严格类型化。
NavigationView 和 NavigationStack 在所有 Apple 平台上运行:iOS、iPadOS、watchOS、tvOS 和 macOS。行为会适应屏幕。在 iPad 上,NavigationStack 支持 NavigationSplitView,它取代了 UIKit 中的 UISplitViewController,在宽屏上显示两列。
NavigationSplitView(iOS 16+)将屏幕分为侧边栏(列表)和详情(详细信息)。在 iPhone 上,侧边栏隐藏,仅通过 NavigationLink 显示详情。在 iPad 上,侧边栏和详情在分屏模式下同时显示。
struct AdaptiveNavigation: View {
@State private var selectedCategory: Category?
var body: some View {
NavigationSplitView {
List(categories, selection: $selectedCategory) { category in
Text(category.name)
}
.navigationTitle("分类")
} detail: {
ProductListView(category: selectedCategory)
}
}
}NavigationSplitView 自动为每个设备选择最佳显示模式。在 iPhone 竖屏模式下——堆栈,在 iPad 和 iPhone 横屏模式下——分屏。开发人员无需为不同的 size class 编写单独的代码。
常见问题
NavigationView — 旧 API(iOS 13-15),仅支持声明式 NavigationLink。NavigationStack — 新 API(iOS 16+),添加了用于程序化导航、深层链接和严格类型化堆栈的 path。Apple 建议新项目使用 NavigationStack。
通过 .toolbar 修饰符和 ToolbarItem。例如:.toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button('设置') { } } }。Placement 决定位置:trailing(右侧)、leading(左侧)、principal(中间)。
标题通过 .navigationTitle('名称') 设置。样式 —— .navigationBarTitleDisplayMode(.large) 或 .inline。Large —— iOS Music 风格的大标题,inline —— 紧凑型,如设置应用中。每个屏幕可以单独更改样式。
三种方式:通过 value(NavigationLink(value:item) { Label }, iOS 16+),通过 destination + label,通过 isActive 进行程序化跳转。带 value 的 NavigationLink 对于列表更简洁,因为不需要在跳转前创建目标 View。
可以。NavigationView 和 NavigationStack 适用于 iOS、iPadOS、watchOS、tvOS 和 macOS。在 watchOS 上,导航使用带有 Digital Crown 滚轮的界面层次结构;在 tvOS 上,使用遥控器的焦点输入。行为会自动适应平台。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。