我是Core Data的新手,我知道如何从实体中添加读取数据,我有两个实体。
这些关系是
在我的应用程序中,我想添加训练和锻炼,它们是训练的子类,我在创建实体(codegen是手动的)后,自动创建了NSManagedObject子类,但没有改变。
在创建实体后(codegen是手动的),我自动创建了NSManagedObject子类,并且没有改变它们。
我的 ContentView.swift
看起来是这样的。
import SwiftUI
import CoreData
struct ContentView: View {
@State var newTrainingName: String = ""
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Training.name, ascending: true)]) var trainings: FetchedResults<Training>
@Environment(\.managedObjectContext) var viewContext
var body: some View {
NavigationView {
VStack {
Group {
VStack {
TextField("Name", text: $newTrainingName)
.padding()
.background(Color.white)
.cornerRadius(15)
Button(action: {
let training = Training(context: self.viewContext)
training.name = self.newTrainingName
try! self.viewContext.save()
}) {
Text("Add")
.padding()
}
}
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)))
.cornerRadius(15)
}
.padding()
List (trainings, id: \.self) { training in
NavigationLink(destination: WorkoutView(training: training)) {
Text(training.name!)
}
}
}
.navigationBarTitle(Text("Trainings"))
}
}
}
struct WorkoutView: View {
var training: Training
@State var newWorkoutText: String = ""
@Environment(\.managedObjectContext) var viewContext
var body: some View {
VStack {
Group {
VStack {
TextField("Name", text: $newWorkoutText)
.padding()
.background(Color.white)
.cornerRadius(15)
Button(action: {
let workout = Workout(context: self.viewContext)
workout.name = self.newWorkoutText
self.training.addToWorkouts(workout)
try! self.viewContext.save()
}) {
Text("Add")
.padding()
}
}
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)))
.cornerRadius(15)
}
.padding()
List (training.workouts ?? [], id: \.self) { workout in
Text(workout.name!)
}
}
}
}
对于 ContentView()
一切都在正常工作。我对 WorkoutView()
我想在Core Data中添加训练并显示它们。
在 Training+CoreDataProperties.swift
我换了
@NSManaged public var workouts: NSSet?
到
@NSManaged public var workouts: [Workout]?
因为我觉得这很有意义。但这仍然是迷失自己的一部分。
另外我还发现了这个自动生成的代码,看起来是对的,但我不知道如何在我的代码中使用它。
// MARK: Generated accessors for workouts
extension Training {
@objc(addWorkoutsObject:)
@NSManaged public func addToWorkouts(_ value: Workout)
@objc(removeWorkoutsObject:)
@NSManaged public func removeFromWorkouts(_ value: Workout)
@objc(addWorkouts:)
@NSManaged public func addToWorkouts(_ values: NSSet)
@objc(removeWorkouts:)
@NSManaged public func removeFromWorkouts(_ values: NSSet)
}
确保你已经在Core Data中设置了关系,就像在.xcdatamodelid中一样,包括反向关系。
我还建议用do catch代替 try!
以获得更好的UI。
你在核心数据中的关系应该是这样的。
在训练实体: 关系: Workouts,Destination: Workout,Inverse: Training
在锻炼实体:关系。训练,目的地。训练,逆向:锻炼
你应该可以在你的按钮动作中完成这个操作。
let workout = Workout(context: self.viewContext)
workout.name = self.newWorkoutText
workout.training = self.training
do {
try self.viewContext.save()
} catch { print(error) }
self.training.addToWorkouts(workout)是怎么来的?这看起来不对。
你想在WorkoutView中把训练添加到你的锻炼中。这种关系就像任何属性一样,所以只要用=将训练分配给它就可以了。