SwiftUI 4中使用navigationDestination(isPresented)返回指定视图问题
问题背景
在SwiftUI 4中使用navigationDestination(isPresented)推送视图,尝试通过重置NavigationPath返回根视图时,控制台打印path计数已变为0,但视图并未返回;追加path的方式也无法生效。
附原测试代码:
import SwiftUI struct View1: View { @State var goToView2 = false @State var path = NavigationPath() var body: some View { NavigationStack(path: $path) { VStack { Text("View 1") Button("Go to View 2") { goToView2 = true } }.navigationDestination(isPresented: $goToView2) { View2(path: $path) } } } } struct View2: View { @State var goToView3 = false @Binding var path: NavigationPath var body: some View { VStack { Text("View 2") Button("Go to View 3") { goToView3 = true } }.navigationDestination(isPresented: $goToView3) { View3(path: $path) } } } struct View3: View { @Binding var path: NavigationPath var body: some View { VStack { Text("View 3") Button("Go to View 1") { print("Before: \(path.count)") path = .init() print("After: \(path.count)") } } } }
运行效果:
问题原因
navigationDestination(isPresented)是基于布尔状态的导航方式,通过这种方式推送的视图不会被加入到NavigationPath的栈中,因此修改NavigationPath无法影响这类视图的导航层级。
解决方法
推荐统一使用NavigationPath的栈管理方式来实现导航,具体步骤如下:
1. 定义导航标识类型
创建一个遵循Hashable协议的枚举,用来标记不同的导航目标:
enum NavDestination: Hashable { case view2 case view3 }
2. 修改导航逻辑为Path驱动
将所有推送视图的操作改为向NavigationPath中追加标识,并用navigationDestination(for:)匹配对应视图:
完整修改后的代码:
import SwiftUI enum NavDestination: Hashable { case view2 case view3 } struct View1: View { @State var path = NavigationPath() var body: some View { NavigationStack(path: $path) { VStack { Text("View 1") Button("Go to View 2") { path.append(NavDestination.view2) } } .navigationDestination(for: NavDestination.self) { destination in switch destination { case .view2: View2(path: $path) case .view3: View3(path: $path) } } } } } struct View2: View { @Binding var path: NavigationPath var body: some View { VStack { Text("View 2") Button("Go to View 3") { path.append(NavDestination.view3) } } } } struct View3: View { @Binding var path: NavigationPath var body: some View { VStack { Text("View 3") // 返回根视图 Button("Go to View 1") { path = .init() } // 返回上一级视图 Button("Go back to View 2") { path.removeLast() } // 返回指定层级(比如跳过一级回到根) Button("Jump to View 1 directly") { path.removeLast(2) } } } }
3. 额外说明
- 这种方式下,所有导航操作都由
NavigationPath统一管理,重置path、移除指定数量的栈元素都能精准控制导航层级。 - 如果必须保留
isPresented的导航方式,需要逐层绑定布尔状态,点击返回时将所有上层的布尔值设为false,但这种方式在多层导航时会导致代码冗余,不推荐。
内容的提问来源于stack exchange,提问作者EmeraldLockdown
相关产品推荐
相关产品推荐

