SwiftData一对多对多关系中ESet删除后数据残留问题求助
SwiftData一对多关系中删除子对象未清理数据库的解决方案
问题核心
你遇到的问题本质是EInfo与ESet之间的双向关系未正确配置,导致SwiftData的.cascade删除规则未生效:从eInfo.sets中移除ESet时,仅切断了关联关系,但数据库里的ESet实例仍被保留。
修复步骤
1. 修正模型的双向关联配置
SwiftData的级联删除依赖正确的双向@Relationship关联,需要为两个类的关系属性明确指定反向关联:
@Model class EInfo { @Attribute(.unique) var id: UUID var exerciseID: String // 明确指定反向关联为ESet的exercise属性,保留.cascade删除规则 @Relationship(deleteRule: .cascade, inverse: \ESet.exercise) var sets: [ESet] var index : Int // 同时明确与Workout的双向关联 @Relationship(inverse: \Workout.exercises) var workout: Workout? = nil // 其余初始化和方法代码不变 } @Model class ESet { @Attribute(.unique) var id: UUID var index: Int var weight: Double // 明确指定反向关联为EInfo的sets属性 @Relationship(inverse: \EInfo.sets) var exercise: EInfo? = nil var weight_ : Double{ get {weight} set {weight = newValue} } var reps: Int var done: Bool = false // 其余初始化代码不变 }
配置后,SwiftData能识别到EInfo.sets和ESet.exercise是双向绑定关系,执行移除操作时会触发.cascade规则,自动删除数据库中的ESet实例。
2. 简化删除逻辑
你当前的删除代码冗余,可简化为直接处理排序后的集合,确保索引对应正确的ESet:
.onDelete(perform: { indexSet in let sortedSets = exerciseInfo.sets.sorted(by: { $0.index < $1.index }) indexSet.forEach { index in guard index < sortedSets.count else { return } let targetSet = sortedSets[index] exerciseInfo.sets.removeAll(where: { $0.id == targetSet.id }) } })
3. 优化ESet添加逻辑
添加新ESet时,手动设置反向关联可避免关联延迟或失效:
.onTapGesture { let newSet = ESet(index: exerciseInfo.sets.count, done: false) newSet.exercise = exerciseInfo exerciseInfo.sets.append(newSet) }
验证方法
修改完成后重新运行APP,执行删除操作后用DB Browser查看SQLite数据库:
- 检查
ESet表,被删除的实例应已移除 - 检查SwiftData自动生成的关联表,对应关联记录也会被清理
内容的提问来源于stack exchange,提问作者rgarg02
相关产品推荐
相关产品推荐

