SwiftUI导航NavigationStack
SwiftUI导航NavigationStack

SwiftUI导航NavigationStack

NavigationStack 是 SwiftUI 在 iOS 16/macOS 13 引入的新一代导航容器,算是对老的 NavigationView的替代品。它背后的设计哲学和用法变化挺大,尤其是更接近 UIKit 里的 UINavigationController 或 AppKit 的导航逻辑。

基本作用

它的核心作用和 NavigationView 类似:在多个视图之间建立层级式(栈式)的导航关系。但它提供了更强的控制能力,可以直接操作导航栈(stack)的内容,而不仅仅是 “点一个 link → push 一个页面”。

基本用法

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("去详情页 1") {
                    DetailView(text: "这是详情页 1")
                }
                
                NavigationLink("去详情页 2") {
                    DetailView(text: "这是详情页 2")
                }
            }
            .navigationTitle("首页")
        }
    }
}

struct DetailView: View {
    let text: String
    
    var body: some View {
        Text(text)
            .navigationTitle("详情")
            .navigationBarTitleDisplayMode(.inline)
    }
}

NavigationStack 是最外层容器。

NavigationLink 用来跳转到下一个视图。

.navigationTitle() 设置导航栏标题。

.navigationBarTitleDisplayMode(.inline) 可以控制标题样式(大标题 / 小标题)。

核心特点

1、显式栈管理

以前 NavigationView 下只能用 NavigationLink 隐式 push/pop。

NavigationStack 提供了一个 path 属性(通常绑定到一个 @State 数组),你可以直接操作这个数组,控制导航栈里的所有页面。

@State private var path: [String] = []

var body: some View {
    NavigationStack(path: $path) {
        List {
            Button("跳到详情 A") {
                path.append("A")
            }
            Button("跳到详情 B") {
                path.append("B")
            }
        }
        .navigationDestination(for: String.self) { value in
            Text("这是详情页 \(value)")
        }
    }
}

在这里,path 就是栈,你追加元素就是 push,移除就是 pop。

2、navigationDestination 的解耦

不需要像 NavigationLink 那样直接在写按钮时就塞入目标视图。

可以统一声明:对于某种类型的数据(比如 String、User、Article),跳转到哪个视图。

这样做更符合数据驱动的思维,也让代码更清晰。

3、更灵活的深层导航

可以一次性把 path 设置为 [“A”, “B”, “C”],直接跳转到三级页面,适合深层连接

这在旧的 NavigationView 里几乎是不可能的。

4、和老的 NavigationView 区别

NavigationView 更像是“外壳 + 隐式 push/pop”,很多状态不透明(比如很难恢复栈状态)。

NavigationStack 更像“栈的真实数据模型”,你可以完全掌控和恢复。

Apple 也明确表示:新项目尽量用 NavigationStack,旧项目慢慢迁移。

使用 path 手动控制导航栈

除了用 NavigationLink 自动跳转,还可以自己控制导航栈。

struct ContentView: View {
    @State private var path: [String] = []

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Button("跳到详情 A") {
                    path.append("A")
                }
                Button("跳到详情 B") {
                    path.append("B")
                }
            }
            .navigationTitle("首页")
            .navigationDestination(for: String.self) { value in
                DetailView(text: "详情 \(value)")
            }
        }
    }
}

struct DetailView: View {
    let text: String
    
    var body: some View {
        Text(text)
            .navigationTitle(text)
    }
}

@State private var path: [String] 表示当前的导航路径。

.navigationDestination(for:) 告诉 NavigationStack 当遇到某种类型时应该跳转到哪个视图。

手动 path.append(…) 可以模拟 push,path.removeLast() 可以模拟 pop。

常见配合的修饰符

.navigationTitle(“标题”),设置标题。

.navigationBarTitleDisplayMode(.inline / .large),标题样式。

.toolbar { … },添加按钮、菜单。

.toolbar(.hidden, for: .navigationBar),隐藏导航栏。

.navigationDestination(for: Type.self),指定不同数据类型对应的目标视图。

总结

NavigationStack 是 SwiftUI 里“可控导航”的新时代武器:它让导航变成了一个数据问题,而不是一个 UI Hack。

toolbar、navigationTitle等修饰符都依赖导航容器使用。

扩展文章

1、SwiftUI导航栏标题navigationTitle:https://fangjunyu.com/2025/09/12/swiftui%e5%af%bc%e8%88%aa%e6%a0%8f%e6%a0%87%e9%a2%98navigationtitle/

2、SwiftUI在iOS中的toolbar工具栏:https://fangjunyu.com/2024/12/07/swift-toolbar%e5%b7%a5%e5%85%b7%e6%a0%8f/

3、SwiftUI导航视图控件NavigationLink:https://fangjunyu.com/2024/12/11/swiftui%e5%af%bc%e8%88%aa%e8%a7%86%e5%9b%be%e6%8e%a7%e4%bb%b6navigationlink/

4、Swift删除NavigationLink自带的颜色效果:https://fangjunyu.com/2024/10/27/swift%e5%88%a0%e9%99%a4navigationlink%e8%87%aa%e5%b8%a6%e7%9a%84%e9%a2%9c%e8%89%b2%e6%95%88%e6%9e%9c/

5、SwiftUI隐藏NavigationLink视图的返回按钮:https://fangjunyu.com/2025/03/13/swiftui%e9%9a%90%e8%97%8fnavigationlink%e8%a7%86%e5%9b%be%e7%9a%84%e8%bf%94%e5%9b%9e%e6%8c%89%e9%92%ae/

6、SwiftUI请求评分requestReview和NavigationLink冲突问题:https://fangjunyu.com/2025/02/27/swiftui%e8%af%b7%e6%b1%82%e8%af%84%e5%88%86requestreview%e5%92%8cnavigationlink%e5%86%b2%e7%aa%81%e9%97%ae%e9%a2%98/

7、SwiftUI在TabView中使用NavigationLink跳转失败的问题:https://fangjunyu.com/2025/05/09/swiftui%e5%9c%a8tabview%e4%b8%ad%e4%bd%bf%e7%94%a8navigationlink%e8%b7%b3%e8%bd%ac%e5%a4%b1%e8%b4%a5%e7%9a%84%e9%97%ae%e9%a2%98/

8、Xcode报错:A NavigationLink is presenting a value of type “Int” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated. https://fangjunyu.com/2024/11/24/xcode%e6%8a%a5%e9%94%99%ef%bc%9aa-navigationlink-is-presenting-a-value-of-type-int-but-there-is-no-matching-navigationdestination-declaration-visible-from-the-location-of-the-link-t/

9、SwiftUI配置深层链接:https://fangjunyu.com/2025/02/08/swiftui%e9%85%8d%e7%bd%ae%e6%b7%b1%e5%b1%82%e9%93%be%e6%8e%a5/

10、SwiftUI导航NavigationView:https://fangjunyu.com/2025/09/12/swiftui%e5%af%bc%e8%88%aanavigationview/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注