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

SwiftUI中NavigationLink跳转新视图时如何关闭当前视图

实现NavigationLink跳转新视图时关闭当前视图

完全可以实现。需要注意的是,不能在点击NavigationLink的瞬间直接调用dismiss()关闭当前页:SwiftUI导航是典型的栈结构,新视图会被压在当前视图上层,如果当前视图在新视图完成push入栈前就被销毁,还没加载完成的新视图会被一起回收,直接导致跳转失败。

根据项目支持的最低iOS版本,选择对应实现方案即可:

  • iOS 16及以上(推荐方案,无兼容问题)

    用NavigationStack的路径管理能力直接操作导航栈,替换栈顶元素即可,不需要加额外延迟,逻辑完全可控。
    首先在导航栈的承载根视图定义统一路由和导航路径状态:

    // 统一管理App内跳转页面的路由枚举
    enum AppRoute: Hashable {
        case login, createAccount
    }
    
    struct RootView: View {
        @State private var navPath = NavigationPath()
        
        var body: some View {
            NavigationStack(path: $navPath) {
                // 导航栈根页面,比如你的欢迎页
                WelcomeView()
                    .navigationDestination(for: AppRoute.self) { route in
                        switch route {
                        case .login:
                            Login(navPath: $navPath)
                        case .createAccount:
                            CreateAccount()
                        }
                    }
            }
        }
    }
    

    之后修改Login视图代码,点击创建账号时直接替换栈顶的Login为CreateAccount,实现跳转后栈内不存在Login页面,返回时不会回退到登录页:

    struct Login: View {
        @Binding var navPath: NavigationPath
        
        var body: some View{
            VStack{
                HStack{
                    Button(action: {
                        // 点击关闭按钮直接移除栈顶的Login,返回上一级
                        navPath.removeLast()
                    }) {
                        Image(systemName: "xmark")
                            .resizable()
                            .frame(width: 18, height: 18)
                    }
                }
                
                Button {
                    // 先弹出栈顶的Login,再压入CreateAccount
                    // 用户视觉上就是直接跳转至创建账号页,无感知
                    navPath.removeLast()
                    navPath.append(AppRoute.createAccount)
                } label: {
                    Text("create account")
                }
            }
        }
    }
    
  • iOS 15及以下版本兼容方案

    如果项目还在使用NavigationView,可以监听NavigationLink的激活状态,等新视图完成push入栈后再关闭当前Login页,加一个极短的延迟避免新视图被一起销毁:

    struct Login: View {
        @Environment(\.presentationMode) var presentationMode
        @State private var isPushToCreateAccount = false
    
        var body: some View{
            VStack{
                HStack{
                    Button(action: {
                        presentationMode.wrappedValue.dismiss()
                    }) {
                        Image(systemName: "xmark")
                            .resizable()
                            .frame(width: 18, height: 18)
                    }
                }
    
                NavigationLink(
                    destination: CreateAccount().navigationBarBackButtonHidden(true),
                    isActive: $isPushToCreateAccount
                ) {
                    Text("create account")
                }
                .onChange(of: isPushToCreateAccount) { active in
                    guard active else { return }
                    // 延迟0.2-0.4秒,等新视图完成渲染入栈后再关闭Login
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
                        presentationMode.wrappedValue.dismiss()
                    }
                }
            }
        }
    }
    

注意:延迟时长不需要设置太长,用户完全感知不到等待,只要保证新视图已经完成push流程即可,不会造成界面卡顿。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 07:48:32