You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NavigationStack重复推送根视图ViewA失效问题咨询

问题重现代码

原始App入口

@main
struct StacksApp: App {
    var body: some Scene {
        WindowGroup {
            ViewA(someText: "Root View")
        }
    }
}

原始ViewA(根视图)

struct ViewA: View {
    private let someText: String?
    private let someNumber: Int?

    @State private var navigationPath = NavigationPath()

    init(someText: String? = nil,
         someNumber: Int? = nil) {
        self.someText = someText
        self.someNumber = someNumber
    }

    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack(spacing: 10) {
                if let someText {
                    Text("Showing \(someText) text")
                } else if let someNumber {
                    Text("Showing \(someNumber) number")
                }

                NavigationLink("Show View B", value: "ViewB")
            }
            .navigationDestination(for: String.self) { value in
                if value == "Hello" {
                    ViewA(someText: value)
                } else {
                    ViewB(path: $navigationPath)
                }
            }
            .navigationDestination(for: Int.self) { value in
                ViewA(someNumber: value)
            }
        }
    }
}

原始ViewB

struct ViewB: View {
    @Binding var path: NavigationPath

    var body: some View {
        VStack(spacing: 10) {
            Text("Hello, World!, this is View B!")
            NavigationLink("Go to ViewA - Showing Int value", value: 4)
            NavigationLink("Go to viewA Showing text Value", value: "Hello")
        }
        .navigationDestination(for: Int.self) { value in
            ViewA(someNumber: value)
        }
    }
}

问题描述

从ViewB点击跳转按钮,试图打开携带不同数据(如Int类型参数)的ViewA时,新视图被推入栈后会立即弹回原始根视图ViewA(someText: "Root View")。但如果将目标视图替换为其他可重复展示的视图(如ViewB),则跳转正常。

原因分析

这不是“禁止重复推送根视图”的设计特性,而是错误嵌套NavigationStack导致的问题:

  • 原始代码中,ViewA作为根视图内部又创建了一个自己的NavigationStack和@State navigationPath
  • 当从ViewB跳转新的ViewA时,新的ViewA会初始化并创建独立的导航栈容器,这会导致系统的导航层级逻辑混乱,最终触发异常回退

解决方案

将NavigationStack提升到App的根层级,让整个应用共享一个导航路径,ViewA作为普通视图参与导航,不再嵌套独立的导航栈。

修改后的代码

根App入口(统一管理导航栈)

@main
struct StacksApp: App {
    @State private var navigationPath = NavigationPath()
    
    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $navigationPath) {
                ViewA(someText: "Root View")
                    // 统一注册所有导航目标
                    .navigationDestination(for: String.self) { value in
                        if value == "Hello" {
                            ViewA(someText: value)
                        } else {
                            ViewB(path: $navigationPath)
                        }
                    }
                    .navigationDestination(for: Int.self) { value in
                        ViewA(someNumber: value)
                    }
            }
        }
    }
}

ViewA(移除内部导航栈)

struct ViewA: View {
    private let someText: String?
    private let someNumber: Int?

    init(someText: String? = nil,
         someNumber: Int? = nil) {
        self.someText = someText
        self.someNumber = someNumber
    }

    var body: some View {
        VStack(spacing: 10) {
            if let someText {
                Text("Showing \(someText) text")
            } else if let someNumber {
                Text("Showing \(someNumber) number")
            }

            NavigationLink("Show View B", value: "ViewB")
        }
    }
}

ViewB(移除多余的导航目标注册)

struct ViewB: View {
    @Binding var path: NavigationPath

    var body: some View {
        VStack(spacing: 10) {
            Text("Hello, World!, this is View B!")
            NavigationLink("Go to ViewA - Showing Int value", value: 4)
            NavigationLink("Go to viewA Showing text Value", value: "Hello")
        }
    }
}

修改后,整个应用只有一个根导航栈,所有视图共享同一导航路径,ViewA可以被多次推入栈中并携带不同参数,跳转行为恢复正常。

内容的提问来源于stack exchange,提问作者Robert Clegg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:25:55