Для контекста знайте, что я совершенно новичок в 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)
}
}
}