提问人:David Schilling 提问时间:7/4/2023 最后编辑:HangarRashDavid Schilling 更新时间:9/26/2023 访问量:1042
Swift数据建模和保存不可为 null 的关系
SwiftData Modeling and saving non Nullable Relations
问:
我有以下代码:
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
var schoolClass: SchoolClass
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
Button("add", action: {
let schoolClassSubject = SchoolClassSubject(schoolClass: schoolClass)
schoolClass.schoolClassSubjects.append(schoolClassSubject)
})
}
.padding()
}
}
@Model
class SchoolClass {
var name: String
var schoolClassSubjects: [SchoolClassSubject] = []
init(name: String) {
self.name = name
}
}
@Model
class SchoolClassSubject {
var schoolClass: SchoolClass
init(schoolClass: SchoolClass) {
print("test")
self.schoolClass = schoolClass
}
}
schoolClass
已保存在 swiftData 中,并作为属性传递给 。ContentView
换行符,但出现以下异常:let schoolClassSubject = SchoolClassSubject(schoolClass: schoolClass)
由于未捕获的异常“NSInvalidArgumentException”而终止应用,原因:“非法尝试在不同上下文中的对象之间建立关系”schoolClass“(源 = <NSManagedObject:0x60000214cc30>(实体:SchoolClassSubject;id:0x60000024ebe0 x-coredata:///SchoolClassSubject/t186670BB-357C-400C-8D6F-178BEB8F4B473;数据:{ schoolClass = nil;}) ,目标 = <NSManagedObject:0x60000214cd70>(实体:SchoolClass;id:0x600000276740 x-coredata:学校班级/t186670BB-357C-400C-8D6F-178BEB8F4B472;data: { name = test; schoolClassSubjects = ( ); }))'第一次抛出呼叫
如果我将我的模型更改为:
@Model
class SchoolClassSubject {
var schoolClass: SchoolClass? = nil
init() {
}
}
我的保存代码如下:
let schoolClassSubject = SchoolClassSubject()
modelContext.insert(schoolClassSubject)
schoolClassSubject.schoolClass = schoolClass
schoolClass.schoolClassSubjects.append(schoolClassSubject)
但我不想做可选,因为它不是现实。我怎样才能使它不是可选的,并且仍然保存它而不会出现给定的错误?schoolClass
schoolClassSubject
答:
这个答案是使用 Xcode 15.0 beta 2 编写的,在未来的版本中,我认为这个答案将变得无关紧要,我们可以更轻松地处理这个问题
再一次,您必须使用注释才能使关系正常工作,一旦您拥有该注释,SwiftData 将为您处理它们。@Relationship
因此,您不应在模型的任何方法中包含任何关系属性。init
因此,将 init 更改为SchoolClassSubject
init() {}
(我不知道我们在这里需要一个空的 init 是一个错误,还是这只是一个奇怪的情况,因为没有其他属性)
然后将按钮操作中的代码更改为
let schoolClassSubject = SchoolClassSubject()
modelContext.insert(schoolClassSubject)
schoolClassSubject.schoolClass = schoolClass
为了澄清上面的代码:
- 首先创建模型对象的实例
- 然后将对象插入到模型上下文中
- 最后,将任何关系属性分配给您的对象
- (保存)
评论
schoolClass
schoolClassSubject
Think it depends on how to keep track of your RelationShip.
If One To Many Relation.
SchoolClass kan have many SchoolClassSubject
SchoolClassSubject only belong to one SchoolClass
@Model
class SchoolClass {
var name: String
@Relationship(deleteRule: .cascade)
var schoolClassSubjects =[SchoolClassSubject]()
init(name: String) {
self.name = name
}
}
@Model
class SchoolClassSubject {
var schoolClassSubject: String
@Relationship(inverse: \SchoolClass.schoolClassSubjects)
var schoolClass: SchoolClass? // ? meaning of optional
init(schoolClassSubject: String) {
//print("test")
self.schoolClassSubject = schoolClassSubject
}
}
// then in WindowGroup you have to have
.modelContainer(for: SchoolClass .self
//In Views
@Environment(\.modelContext) private var context
let schoolClass: SchoolClass
// You can do in Views save func
let transaction = SchoolClassSubject(schoolClassSubject: "String here..")
transaction.schoolClass = schoolClass
评论