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

SwiftUI 如何从其他视图更新类内数组中结构体的count属性

编译报错核心原因

Swift的ForEach遍历值类型数组时,闭包默认将取出的元素声明为不可变let常量,你代码里写的day.count += 1是尝试修改不可变常量的属性,这就是触发报错的直接原因:

Left side of mutating operator isn't mutable: 'day' is a 'let' constant

另外需要注意一个容易忽略的点:SingleDay是结构体(值类型),循环闭包里拿到的day是原数组元素的临时拷贝,哪怕你强行让这个变量变成可变的,修改的也只是内存里的临时副本,既不会改动真实数据源,也不会触发任何视图刷新。

可正常运行的修改逻辑

你已经用了共享的Days ObservableObject作为全局数据源——UpdatingArrayElements里的@StateObject days和TestScreen里的@ObservedObject dayViewModel是同一个内存实例,只要直接修改这个实例里被@Published修饰的daysArray数组,两个视图都会自动收到数据变更通知、重新渲染UI,完全满足“count修改同步反映到UpdatingArrayElements”的需求。
具体的实现逻辑是:跳过循环拿到的临时值副本,通过元素自带的唯一id,定位元素在原数组里的真实下标,直接通过数组下标修改元素属性。

替换TestScreen中的错误代码

把原有按钮内直接修改day.count的逻辑,替换为按id匹配原数组下标的写法,参考实现:

VStack {
    ForEach(dayViewModel.daysArray) { day in
        Text(String(day.day))
        Button(action: {
            // 通过元素的唯一id匹配在原数组中的位置
            guard let index = dayViewModel.daysArray.firstIndex(where: { $0.id == day.id }) else {
                return
            }
            // 直接修改原数组对应位置的count属性
            dayViewModel.daysArray[index].count += 1
        }, label: {
            Text("Add count")
        })
    }
}
新手避坑提示
  • 不要尝试给ForEach闭包里的遍历变量加var来绕过编译报错:这种写法修改的只是值类型的临时副本,和你持有的数据源没有关联,哪怕编译过了,UI也不会有任何实际变化。
  • 只要数组里存的是值类型元素,要修改它的内部属性,必须拿到数组的真实下标做写入操作,不能直接修改遍历流程中生成的临时变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 20:54:05