SwiftUI中@Environment(\.dismiss)返回至根视图而非上一级的问题
问题现象
开发SwiftUI项目时,根视图LoginView嵌入在NavigationStack中,使用.navigationDestination修饰器依次跳转到Screen A、Screen B后,点击Screen B中基于@Environment(\.dismiss)实现的返回按钮,并未回到Screen A,而是直接返回至根视图LoginView。但使用已被Apple弃用的NavigationLink跳转时,返回功能正常。
问题根源
每个子视图(Screen A、Screen B)都重复创建了独立的NavigationStack。SwiftUI的NavigationStack负责维护整个导航层级,根视图的NavigationStack已经管理了完整的导航栈,子视图再嵌套NavigationStack会导致每个页面处于各自独立的导航栈中。此时调用dismiss()只会关闭当前子视图的独立导航栈,直接回到根视图的导航层级。
修正代码
移除Screen A和Screen B中的NavigationStack,让所有页面共享根视图的导航栈:
// LoginView (Root view) struct LoginView: View { @State var moveToScreenA: Bool = false var body: some View { NavigationStack { VStack(alignment: .leading, spacing: 0) { Button { moveToScreenA = true } label: { Text("Registration") } } .navigationDestination(isPresented: $moveToScreenA) { ScreenA() } } } } // Screen A struct ScreenA: View { @State var moveToScreenB: Bool = false var body: some View { VStack(alignment: .leading, spacing: 0) { Button { moveToScreenB = true } label: { Text("Next") } } .navigationDestination(isPresented: $moveToScreenB) { ScreenB() } } } // Screen B struct ScreenB: View { @Environment(\.dismiss) var dismiss var body: some View { VStack(alignment: .leading, spacing: 0) { Button { dismiss() } label: { Image(.BACK_DARK) } } } }
补充说明
修正后所有页面都处于同一个根NavigationStack的导航层级中,调用dismiss()时会正确回到上一级页面(Screen B→Screen A→LoginView)。如果需要更灵活地控制导航路径,也可以使用NavigationStack的path绑定方式,通过数组来管理导航栈的状态,进一步提升导航逻辑的可控性。
内容的提问来源于stack exchange,提问作者Nisar Ahmad
相关产品推荐
相关产品推荐

