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

SwiftUI弹窗Alert首次点击确认按钮无响应问题求助

问题原因与解决方案

你的代码首次点击Confirm无响应,核心原因是状态更新的竞态冲突:

  • TextField直接绑定self.options.name,而Confirm按钮的disabled状态完全依赖这个值是否为空。
  • 首次输入名称后,options.name的状态更新与Alert的isPresented(即isShowingNameInput)状态更新(点击Confirm需关闭Alert)几乎同步触发,SwiftUI异步的视图更新机制导致首次点击时,按钮的action被状态更新流程干扰,没能正常执行。

修复方案一:分离输入状态(推荐)

新增一个本地@State变量专门绑定TextField的输入内容,点击Confirm时再将值同步到options,彻底规避状态冲突:

// 在视图内部添加本地输入状态变量
@State private var tempTaskName = ""

// 修改原按钮与Alert代码
Button(action: {
  self.isShowingNameInput = true
  // 弹出Alert时清空临时输入框
  self.tempTaskName = ""
}) {
  Text("SAVE")
}
.alert("Task Name", isPresented: self.$isShowingNameInput, actions: {
  TextField("", text: self.$tempTaskName)  

  Button(action: {
    // 将临时输入值同步到options
    self.options.name = self.tempTaskName
    log("Saved \(self.options.name)")
    self.presentationMode.wrappedValue.dismiss()
  }) {
    Text("Confirm")
  }.disabled(self.tempTaskName.isEmpty)

  Button(role: .cancel, action: {}) {
    Text("Cancel")
  }
}, message: {})

修复方案二:调整状态更新顺序

如果不想新增本地变量,可以手动指定状态更新顺序,确保Alert先完成关闭流程,再执行后续操作:

Button(action: {
  // 先关闭Alert,再延迟执行日志与返回操作
  self.isShowingNameInput = false
  DispatchQueue.main.async {
    log("Saved \(self.options.name)")
    self.presentationMode.wrappedValue.dismiss()
  }
}) {
  Text("Confirm")
}.disabled(self.options.name.isEmpty)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:27:13