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

SwiftUI中ConfirmationDialog点击Cancel自动返回首页的Bug修复

问题解决方法

核心原因

该问题源于NavigationView与TabView的嵌套结构冲突,以及NavigationLink的isActive绑定在弹窗交互时被意外触发重置。当ConfirmationDialog关闭时,系统导航状态被干扰,导致绑定的settingActive被自动设为false,触发返回首页的操作。

修复方案

以下两种方式均可解决该问题,优先推荐方式一,更符合SwiftUI导航设计规范:

方式一:调整导航结构(推荐)

将NavigationView移到TabView的子页面内部,避免导航状态的层级冲突:

import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                VStack {
                    // 直接使用普通NavigationLink,无需isActive绑定
                    NavigationLink(destination: SettingView()) {
                        Text("Setting")
                    }
                }
                .padding()
            }
            .tabItem {
                Text("Home")
            }
        }
    }
}

struct SettingView: View {
    @State private var logoutActive: Bool = false
    
    var body: some View {
        VStack {
            Button {
                logoutActive.toggle()
            } label: {
                Text("Logout")
            }
            .confirmationDialog("Logout", isPresented: $logoutActive) {
                Button("Logout", role: .destructive) {
                    // 执行登出逻辑
                }
            }
        }
        .navigationTitle("Settings")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

方式二:手动控制弹窗与返回状态

保留原有结构的前提下,显式声明Cancel按钮并使用环境变量控制返回,避免默认弹窗按钮干扰绑定状态:

import SwiftUI

struct ContentView: View {
    @State private var settingActive: Bool = false
    
    var body: some View {
        NavigationView {
            TabView {
                VStack {
                    NavigationLink(destination: SettingView(), isActive: $settingActive) {
                        EmptyView()
                    }

                    Button {
                        settingActive.toggle()
                    } label: {
                        Text("Setting")
                    }
                }
                .padding()
            }
        }
    }
}

struct SettingView: View {
    @State private var logoutActive: Bool = false
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        VStack {
            Button {
                logoutActive.toggle()
            } label: {
                Text("Logout")
            }
            .confirmationDialog("Logout", isPresented: $logoutActive) {
                Button("Logout", role: .destructive) {
                    // 执行登出逻辑后手动返回
                    dismiss()
                }
                // 显式声明Cancel按钮,避免系统默认按钮干扰状态
                Button("Cancel", role: .cancel) {
                    logoutActive = false
                }
            } message: {
                Text("确认要登出吗?")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

关键说明

  • 显式声明Cancel按钮可以避免系统自动生成的默认按钮意外修改绑定状态
  • 方式一通过调整导航层级,从根源上消除了状态冲突的可能性,是更稳妥的方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:40:59