iOS 14 SwiftUI:如何从View3返回至含View1的RootView
iOS 14 SwiftUI 从View3导航回显示View1的RootView解决方案
在iOS 14的SwiftUI中,由于还未引入NavigationStack和直接返回根视图的原生API,我们可以通过绑定状态管理或全局导航状态对象来实现从View3直接回到显示View1的RootView,以下是具体实现方案:
方案:使用ObservableObject管理全局导航状态
通过创建一个可观察对象来统一管理所有导航视图的激活状态,以及RootView中显示View1的条件,这样可以在View3中直接触发状态重置,实现一步返回。
完整代码实现
import SwiftUI // 全局导航状态管理对象 class NavigationManager: ObservableObject { // 控制View1到View2的导航激活状态 @Published var isView2Active = false // 控制View2到View3的导航激活状态 @Published var isView3Active = false // 控制RootView是否显示View1 @Published var showView1 = true } struct RootView: View { // iOS14及以上使用@StateObject管理ObservableObject @StateObject private var navManager = NavigationManager() var body: some View { NavigationView { VStack { if navManager.showView1 { View1() } else { SomeOtherView() } } .navigationTitle("Root") } .navigationViewStyle(.stack) // iOS14需显式设置栈式导航风格 .environmentObject(navManager) // 将状态对象注入环境,供子视图调用 } } struct View1: View { @EnvironmentObject var navManager: NavigationManager var body: some View { NavigationLink( destination: View2(), isActive: $navManager.isView2Active, label: { Text("前往View2") } ) .navigationTitle("View1") } } struct View2: View { @EnvironmentObject var navManager: NavigationManager var body: some View { NavigationLink( destination: View3(), isActive: $navManager.isView3Active, label: { Text("前往View3") } ) .navigationTitle("View2") } } struct View3: View { @EnvironmentObject var navManager: NavigationManager @Environment(\.presentationMode) var presentationMode var body: some View { Button("返回RootView(显示View1)") { // 1. 关闭当前View3视图 presentationMode.wrappedValue.dismiss() // 2. 重置所有导航激活状态 navManager.isView3Active = false navManager.isView2Active = false // 3. 确保RootView显示View1 navManager.showView1 = true } .navigationTitle("View3") } } struct SomeOtherView: View { var body: some View { Text("其他视图") .navigationTitle("其他") } }
方案说明
- NavigationManager:集中管理所有导航相关状态,包括各页面的导航激活状态和RootView的视图显示条件,通过
@Published标记状态变更,确保视图能实时响应更新。 - 环境注入:通过
.environmentObject(navManager)将状态对象注入全局环境,所有子视图可通过@EnvironmentObject直接访问,无需逐层传递绑定。 - 状态重置:在View3的按钮点击事件中,先通过
presentationMode关闭当前视图,再重置所有导航激活状态,并确保showView1为true,最终回到显示View1的RootView。
备选方案:多次调用dismiss(不推荐)
如果导航层级固定(View3→View2→View1→RootView),也可以在View3中连续调用两次presentationMode的dismiss方法,但这种方式依赖固定的导航层级,灵活性差,不推荐使用:
struct View3: View { @Environment(\.presentationMode) var presentationMode var body: some View { Button("返回RootView") { // 第一次关闭View3回到View2 presentationMode.wrappedValue.dismiss() // 延迟关闭View2回到View1(需确保主线程执行) DispatchQueue.main.async { presentationMode.wrappedValue.dismiss() } } } }
内容的提问来源于stack exchange,提问作者Teja Kumar Bethina
相关产品推荐
相关产品推荐

