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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:03:11