Базовое обновление данных по нескольким объектам по ошибке - PullRequest
0 голосов
/ 26 января 2020

Для контекста знайте, что я совершенно новичок в Swift, SwiftUI, Core Data и объектно-ориентированном программировании событий. Я пишу приложение iOS, чтобы попытаться изучить эти фреймворки.

Я пишу базовое c приложение для отслеживания тренировок. Моя базовая модель данных имеет 3 сущности: Exercise со свойствами для exercName и exercNotes и отношения 1-1 к MuscleGroup и Type.

Type, со свойством typeName и отношение 1-Many к Exercise

MuscleGroup, со свойством muscleGroupName и отношением 1-Many к упражнению

Я использую NavigationView для начала со списком всех упражнений и NavigationLink для доступа к подробному виду, который является формой для редактирования существующего списка items.

В подробном представлении у меня есть TextFields для exercName и exercNotes, а также средство выбора для muscleGroupName, которое заполняется постоянным массивом доступных вариантов, и по умолчанию выбор соответствует значению любого выбранного объекта. из списка.

В любом случае, когда я редактирую имя упражнения или имя упражнения, изменение проходит очень хорошо. Если я отредактирую отношение muscleGroup (exerc.exerciseToMuscleGroup.muscleGroupName), изменение сохранится в базовых данных, но, похоже, будет обновлено отношение для каждого объекта в сущности Exercise, имеющего то же значение для exerc.exerciseToMuscleGroup.muscleGroupName. Например, если у меня есть 3 упражнения: - Жим ногами (название группы мышц = ноги) - Завиток бицепса (название группы мышц = руки) - Жим грудью (название группы мышц = грудь)

С этим, если я go и отредактируйте Bicep Curl и измените название группы мышц на Legs, это нормально - это работает. Если я go вернусь к Bicep Curl и вернусь к названию Muscle Group обратно в Arms, он также установит Arms в названии Muscle Group Leg Press, так что теперь и Leg Press, и Curl Bicep имеют «Arms» для exerc.exerciseToMuscleGroup.muscleGroupName. Если я поменяю Chest Press на Muscle Group = Arms, это снова работает, но теперь, если я изменю Muscle Group на любом из 3 упражнений, они ВСЕ обновляются с новой мышечной группой.

Буду признателен за любые рекомендации о том, как правильно это сделать, чтобы обновлялся только тот экземпляр упражнения, который находится в подробном представлении.

//
//  StrengthExerciseDetail.swift


import SwiftUI
import CoreData

struct StrengthExerciseDetail: View {
    @Environment(\.managedObjectContext) var moc
    let exercise: Exercise

    @State private var notes: String
    @State private var name: String
    @State private var muscleGroupName: String
    @State private var muscleGroupIndex: Int = 0
    let muscleGroupNames: [String] = ["Abdominals", "Arms", "Back", "Chest", "Legs", "Shoulders"]

    init(exercise: Exercise) {
        self.exercise = exercise
        // Define the initial form field values
        _notes = .init(initialValue: exercise.wrappedExerciseNotes)
        _name = .init(initialValue: exercise.wrappedExerciseName)
        _muscleGroupName = .init(initialValue: exercise.exerciseToMuscleGroup!.wrappedMuscleGroupName)

        // Set the Muscle Group picker selection
        var currentIndex: Int = 0
        for muscle in muscleGroupNames {
            if muscle == muscleGroupName {
                _muscleGroupIndex = .init(initialValue: currentIndex)
            } else {
                currentIndex += 1
            }
        }
        currentIndex = 0
    }

    func updateExercise(_ exercise: Exercise) {
        print("running update exercise")

        do {
            print("running loop")
            let newMuscleGroupName = muscleGroupNames[muscleGroupIndex]

            exercise.setValue(name, forKey: "exerciseName")
            exercise.setValue(notes, forKey: "exerciseNotes")
            exercise.setValue(newMuscleGroupName, forKeyPath: "exerciseToMuscleGroup.muscleGroupName")
            try moc.save()
            moc.refreshAllObjects()


        } catch {
            print(error)
        }
        moc.reset()
    }

    var body: some View {
        Form {
            Section(header: Text("Exercise Name")) {
                    TextField("Name", text: $name)
            }
            Section(header: Text("Muscle Group")) {
                Picker(selection: $muscleGroupIndex, label: Text("")) {
                    ForEach(0 ..< muscleGroupNames.count) {
                        Text(self.muscleGroupNames[$0])
                    }
                }
            }
            Section(header: Text("Notes")) {
                TextField("Notes", text: $notes)
                    .frame(height: 300.0)
            }
            Button("Save Changes") {
                self.updateExercise(self.exercise)
            }
        }
    }
}

struct StrengthExerciseDetail_Previews: PreviewProvider {
    static let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

    static var previews: some View {
        let exercise = Exercise(context: moc)
        exercise.exerciseName = "Booty Bounce"
        exercise.exerciseNotes = "This is a great strength builder"
        exercise.exerciseToMuscleGroup = MuscleGroup(context: moc)
        exercise.exerciseToMuscleGroup?.muscleGroupName = "Legs"
        exercise.exerciseToType = Type(context: moc)
        exercise.exerciseToType?.typeName = "Strength"

        return NavigationView {
            StrengthExerciseDetail(exercise: exercise)
        }
    }
}
...