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

SwiftUI detail sheet传递列表项时子视图值更新异常问题求解

问题根源

你使用的sheet(isPresented:content:)API存在值捕获机制的缺陷:该API的content闭包会在主视图首次渲染时就完成初始值捕获,后续你修改selectedShoppingList变量时,已创建的sheet闭包不会自动更新捕获的值,因此首次弹出时拿到的是默认的ShoppingList.single,关闭sheet后第二次弹出才会读取到更新后的值,这是SwiftUI sheet的常见适配问题。

解决方案

方案1(推荐):改用sheet(item:content:)API

该API专为依赖选中项的弹窗场景设计,选中项变化时会自动重建sheet,永远传入最新的选中值,无需手动维护弹窗显隐状态:

  1. 首先调整selectedShoppingList为可选类型,同时删除多余的presentCreateSheet状态:
@State var selectedShoppingList: ShoppingList? // 无需再声明presentCreateSheet
  1. 修改按钮点击逻辑,直接赋值选中项即可,系统会自动触发弹窗:
Button {
    self.selectedShoppingList = shoppingList
} label: {
    HomeRowView(shoppingList: shoppingList)
}
  1. 替换原有sheet实现:
.sheet(item: $selectedShoppingList, onDismiss: {
    Task {
        await viewModel.getList()
    }
}, content: { selectedList in
    // 每次弹出都会用最新的选中值初始化ViewModel
    ItemView(viewModel: ItemViewModel(shoppingList: selectedList))
})

注意:需要让ShoppingList遵守Identifiable协议,若暂未适配,也可以使用sheet(item: $selectedShoppingList, id: \.self)的写法(需保证ShoppingList遵守Hashable协议)。

方案2:强制刷新sheet内容

如果不想改动现有代码结构,可以给sheet内的根View绑定唯一标识,每次选中项变化时强制重建View:

.sheet(isPresented: $presentCreateSheet, onDismiss: {
    Task.init {
        await viewModel.getList()
    }
    self.presentCreateSheet = false
}, content: {
    ItemView(viewModel: ItemViewModel(shoppingList: selectedShoppingList))
        // id变化时SwiftUI会销毁旧实例重建,自动读取最新的选中值
        .id(selectedShoppingList.id)
})

额外注意

你当前贴出的ItemViewModel代码中未声明shoppingList属性,需要在类中补充对应的属性定义,如果需要在子视图中响应shoppingList的变化,可以给该属性加上@Published包装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:54:04