Core Data中Int32类型属性修改后Text不立即更新如何解决?
问题根源
这个问题和闭包无关,也不需要替换整个数组,核心原因是你没有对ForEach循环内的Core Data实体实例做属性变更监听:
- Core Data生成的实体类本身是
ObservableObject子类,@StateObject只会在你监听的exeplan本身的属性/关系发生变更时触发刷新(比如你给exercisearray新增/删除元素) - 你现在修改的是
exercisearray内部元素的duration属性,上层的exeplan不会感知到这次变更,所以当前视图不会重绘,只有页面重新初始化时才会读取最新值。
最优解决方案
把列表单项抽成独立子视图,在子视图中用@ObservedObject接收对应的实体实例,子视图会自动监听实体的属性变更,触发实时刷新:
// 抽离的单项视图 struct ExerciseItemView: View { // 监听单个Exercise实体的属性变化 @ObservedObject var item: Exercise @Environment(\.managedObjectContext) private var viewContext var body: some View { HStack { Button { item.duration -= 15 do { try viewContext.save() } catch { print(error.localizedDescription) } } label: { Image(systemName: "minus.circle.fill") } Text("\(item.duration)") Button { item.duration += 15 do { try viewContext.save() } catch { print(error.localizedDescription) } } label: { Image(systemName: "plus.circle.fill") } } } } // 原页面的ForEach替换为以下写法 ForEach(Array(exeplan.exercisearray.enumerated()), id: \.element) { _, item in ExerciseItemView(item: item as! Exercise) }
临时应急方案
如果不想抽离子视图,可以加一个无实际意义的@State变量,每次修改属性后手动触发视图刷新,该方案不推荐长期使用:
// 当前页面新增变量 @State private var refreshFlag = false // 修改按钮的action Button(action: { item.duration -= 15 do { try viewContext.save() refreshFlag.toggle() // 手动触发重绘 } catch {} }, label: { Image(systemName: "minus.circle.fill") })
内容的提问来源于stack exchange,提问作者fatdrogen
相关产品推荐
相关产品推荐

