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

SwiftUI dismiss所有活跃presented视图并pop到根视图ContentView的问题咨询

现有代码的逻辑是点击ThirdView的返回按钮先dismiss当前弹出的sheet,等sheet完全消失后才会触发SecondView的onDismiss回调执行pop操作,这个过程会短暂显示SecondView,无法达到直接返回FirstView的效果。

解决方案:统一管理路由状态,全局控制导航与弹窗显隐

通过ObservableObject封装所有路由状态,注入到视图环境中,底层视图可以直接修改根视图的导航状态,同时临时禁用动画避免中间过渡效果。

完整修改代码:

import SwiftUI

// 统一路由状态管理类
class RouteState: ObservableObject {
    // 控制是否展示push出来的LoginView(对应原代码SecondView)
    @Published var showLoginView = false
    // 控制是否展示present出来的HomeView(对应原代码ThirdView)
    @Published var showHomeView = false
}

struct FirstView: View {
    @StateObject private var routeState = RouteState()
    
    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                Text("FirstView View")
                    .font(.largeTitle)
                    .foregroundColor(.red)
                NavigationLink( destination: SecondView(), isActive: $routeState.showLoginView, label: {
                    Text("Show SecondView")
                })
            }
        }
        .environmentObject(routeState)
    }
}

struct SecondView: View {
    @EnvironmentObject var routeState: RouteState

    var body: some View {
        VStack(spacing: 16) {
            Text("Second View")
                .font(.largeTitle)
                .foregroundColor(Color(.systemPurple))
            Button(action: { routeState.showHomeView = true }, label: {
                Text("Show ThirdView")
                    .padding()
            })
        }
        .sheet(isPresented: $routeState.showHomeView) {
            ThirdView()
                .environmentObject(routeState)
        }
    }
}

struct ThirdView: View {
    @EnvironmentObject var routeState: RouteState
    
    var body: some View {
        VStack(spacing: 16) {
            Text("Third View")
                .font(.largeTitle)
                .foregroundColor(Color(.systemTeal))
            Button(action: {
                // 临时禁用动画,避免中间页过渡效果
                UIView.setAnimationsEnabled(false)
                // 同时关闭弹窗和push导航
                routeState.showHomeView = false
                routeState.showLoginView = false
                // 延迟恢复动画,不影响后续页面交互
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    UIView.setAnimationsEnabled(true)
                }
            }, label: {
                Text("Back to FirstView")
                    .padding()
            })
        }
    }
}

实现说明

  • 所有导航、弹窗的显隐状态统一由RouteState托管,不需要依赖各层视图的presentationMode逐层返回
  • 点击返回时直接将根视图的导航状态、弹窗状态同时置为false,配合临时禁用系统动画,不会出现中间页闪屏的问题
  • 代码兼容iOS13及以上版本,若使用iOS16+可替换为NavigationStack实现更简洁的路由控制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 15:06:05