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
相关产品推荐
相关产品推荐

