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

SwiftUI Combine数据流问题:训练组输入数据无法持久化保存

问题根因

你的数据同步失效完全是属性包装器用法和值/引用类型混用导致的,和@Binding本身无关,核心错误有3个:

  • 第一,CompletedExercise、ExerciseSet被定义为class引用类型,同时给内部属性加了@Published,但嵌套的ObservableObject子类内部属性变更,只会触发自身的objectWillChange通知,不会向上传递给持有它的ExerciseStore,你在输入框修改值的时候,顶层的store完全感知不到变化,持久化时自然拿不到新数据。
  • 第二,对引用类型数组用下标取绑定的写法$exercise.sets[0]无效:class数组的下标访问拿到的是引用的临时拷贝,绑定不会指向原数组内存储的实例,你在SetView里修改的是临时拷贝的属性,原数组里的实例根本没有被更新。
  • 第三,@Published只能监听到值类型的属性变更、或者引用类型整体的指针替换,监听不到引用类型内部的属性变化,哪怕你把class实例存在@Published标注的数组里,修改实例内部属性也不会触发发布事件。
修正方案

优先选第一种,完全符合SwiftUI的数据流设计规范,没有冗余代码:

方案1:将所有数据模型改为struct值类型(推荐)

值类型的变更会被@Published、@Binding自动感知,不需要做嵌套的通知传递,改完链路直接通:

  1. 把CompletedExercise从class改为struct,移除ObservableObject协议遵循,删掉sets属性前的@Published
  2. 把ExerciseSet从class改为struct,移除ObservableObject协议遵循,删掉reps、weight属性前的@Published

修正后的模型代码如下,因为struct的所有属性都遵循Codable,你可以删掉手动写的编码解码逻辑,编译器会自动生成正确实现:

struct CompletedExercise: Codable, Identifiable {
  var id = UUID().uuidString
  var exercise: Exercise
  var sets = [ExerciseSet(), ExerciseSet(), ExerciseSet()]

  init(exercise: Exercise) {
    self.exercise = exercise
  }
}

struct ExerciseSet: Codable {
  var reps: Int?
  var weight: Int?
  init() {}
}

struct Exercise: Codable, Identifiable {
  var id = -1
  var name = "Bench Press"
}

改完之后绑定链路会自动生效:输入框修改值 → 绑定逐层更新struct属性 → 触发ExerciseStore的@Published发布事件,此时调用save()就能拿到最新数据。

方案2:保留class模型(不推荐)

如果业务逻辑必须用引用类型,需要手动给每一层嵌套的ObservableObject实例加订阅,把内部的变更事件转发给上层store,同时不能直接用数组下标取class实例的绑定,需要从store层根据id查找对应实例生成绑定。这个方案需要写大量样板代码,很容易出现循环引用、内存泄漏问题,非必要不要用。

额外补全项

你当前代码没有触发save()的时机,哪怕数据链路通了,修改完值不调用save也不会持久化到UserDefaults,可以给ExerciseStore的completedExercises加didSet监听器,只要数据变更就自动调用save,不需要手动触发:

class ExerciseStore: ObservableObject {
  @Published var completedExercises: [CompletedExercise] = [CompletedExercise(exercise: Exercise())] {
    didSet { save() }
  }
  // 其余原有代码保持不变
}

注意:TextField配合NumberFormatter处理空输入时有已知的绑定失效问题,建议给输入框加数字键盘限制,或者用@FocusState在输入结束时做类型转换,避免输入空值时绑定重置。

内容的提问来源于stack exchange,提问作者Pavel B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:21:29