CoreData多按钮同步问题:如何为每个训练组按钮独立关联数据?
解决方案
1. 修正CoreData实体设计
首先要确保数据模型能区分每个训练组:
- 创建
Set实体,添加以下属性:setNumber:Int16(标记是第1-4组)reps:Int16(记录次数)weight:Double(记录重量)
- 在
Workout实体(你用来表示单次训练的实体)中添加to-many关系(命名为sets)关联到Set,同时给Set实体添加反向关系(命名为workout)关联回Workout,确保数据关联正确。
2. 视图层实现独立绑定
核心思路是:每个训练组按钮对应唯一的Set实体(按setNumber区分),通过当前训练对象的关联关系获取对应组的数据,而非全局拉取所有Set数据。
父视图代码
struct WorkoutView: View { let workout: Workout // 当前训练对象,从上层视图传递 @Environment(\.managedObjectContext) private var viewContext var body: some View { VStack(spacing: 16) { // 遍历1-4组 ForEach(1...4, id: \.self) { setNumber in // 查找当前训练中对应组号的Set实体 let currentSet = workout.sets?.compactMap { $0 as? Set } .first(where: { $0.setNumber == setNumber }) if let set = currentSet { // 已记录的组:显示编辑按钮 EditedTrackButton(set: set) } else { // 未记录的组:显示初始按钮 SetTrackerButton(setNumber: Int16(setNumber), workout: workout) } } } } }
未记录组按钮(SetTrackerButton)
struct SetTrackerButton: View { let setNumber: Int16 let workout: Workout @Environment(\.managedObjectContext) private var viewContext @State private var inputReps = "" @State private var inputWeight = "" @State private var showInputSheet = false var body: some View { Button("Set: \(setNumber)") { showInputSheet = true } .sheet(isPresented: $showInputSheet) { VStack(spacing: 20) { TextField("输入次数", text: $inputReps) .keyboardType(.numberPad) .textFieldStyle(.roundedBorder) TextField("输入重量", text: $inputWeight) .keyboardType(.decimalPad) .textFieldStyle(.roundedBorder) Button("保存") { guard let reps = Int16(inputReps), let weight = Double(inputWeight) else { return } // 创建新的Set实体并关联到当前训练 let newSet = Set(context: viewContext) newSet.setNumber = setNumber newSet.reps = reps newSet.weight = weight newSet.workout = workout try? viewContext.save() showInputSheet = false inputReps = "" inputWeight = "" } } .padding() } } }
已记录组按钮(EditedTrackButton)
struct EditedTrackButton: View { @ObservedObject var set: Set // 监听Set实体的变化 @State private var inputReps = "" @State private var inputWeight = "" @State private var showEditSheet = false var body: some View { Button("\(set.reps) × \(set.weight)") { showEditSheet = true inputReps = "\(set.reps)" inputWeight = "\(set.weight)" } .sheet(isPresented: $showEditSheet) { VStack(spacing: 20) { TextField("修改次数", text: $inputReps) .keyboardType(.numberPad) .textFieldStyle(.roundedBorder) TextField("修改重量", text: $inputWeight) .keyboardType(.decimalPad) .textFieldStyle(.roundedBorder) Button("保存修改") { if let reps = Int16(inputReps) { set.reps = reps } if let weight = Double(inputWeight) { set.weight = weight } try? set.managedObjectContext?.save() showEditSheet = false } } .padding() } } }
关键改进点
- 数据隔离:每个按钮通过
setNumber绑定唯一的Set实体,不会出现所有按钮共用同一批数据的问题。 - 精准获取数据:通过当前
Workout的sets关联关系获取对应组的数据,而非全局拉取所有Set实体,避免数据混淆。 - 响应式更新:使用
@ObservedObject监听单个Set实体的变化,只有对应按钮会刷新,其他按钮不受影响。
内容的提问来源于stack exchange,提问作者user23665023
相关产品推荐
相关产品推荐

