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
相关产品推荐
相关产品推荐

