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

使用popover时@State变量无法更新的技术问题咨询

SwiftUI中.popover(isPresented:)绑定状态时更新不生效的原因

问题场景

你的代码如下:

List(expenses) { expense in
    ExpenseListItemView(expense: expense)
        .swipeActions {
            Button("Edit") {
                selectedExpenseId = expense.id
                showAddExpensePopup = true
            }.tint(.blue)
        }
    }
    .popover(isPresented: $showExpenseEditorPopup) {
        if let id = selectedExpenseId {
            ExpenseEditorScreen(expenseId: id)
        } else {
            ExpenseEditorScreen()
        }
    }
}

其中selectedExpenseId和showAddExpensePopup都是@State变量,点击Edit按钮后,selectedExpenseId的更新无法被popover识别,导致弹窗始终进入else分支,无法加载编辑现有费用的页面。

核心原因

  1. SwiftUI的状态合并更新机制:当你在同一个闭包里连续修改多个@State变量时,SwiftUI不会立即逐个刷新视图,而是会把这些状态变更合并成一次批量更新操作。
  2. .popover(isPresented:)的初始化时机:弹窗的内容视图是在showAddExpensePopup变为true的瞬间,基于当前的状态快照创建的。由于两次状态变更被合并,弹窗初始化时,selectedExpenseId的新值还没同步到视图的状态上下文里,此时selectedExpenseId仍然是初始的nil值,因此会加载空的ExpenseEditorScreen。

简单来说,代码逻辑上是先更新id再弹出窗口,但SwiftUI的批量更新机制让弹窗没来得及拿到新的id值。

而.popover(item:)能解决这个问题,是因为它直接绑定可选类型的数据源(比如Expense对象或其id),只有当数据源不为nil时才触发弹窗,弹窗内容直接基于绑定的数据源,从根源上避免了状态不同步的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 08:43:21