SwiftData 建模和保存非空关系

Dav*_*ing 6 swift swift-data swiftui

我有以下代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

schoolClass已保存在 swiftData 中并作为属性传递给ContentView.

换行符let schoolClassSubject = SchoolClassSubject(schoolClass: schoolClass)有以下例外情况:

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“非法尝试在不同上下文中的对象之间建立关系“schoolClass”(源= <NSManagedObject:0x60000214cc30>(实体:SchoolClassSubject;id:0x60000024ebe0 x-coredata: ///SchoolClassSubject/t186670BB-357C-4​​00C-8D6F-178BEB8F4B473; data: { schoolClass = nil; }) , 目的地 = <NSManagedObject: 0x60000214cd70> (实体: SchoolClass; id: 0x600000276740 x-coredata:///SchoolClass/t186670 BB -357C-4​​00C-8D6F-178BEB8F4B472; data: { name = test; schoolClassSubjects = ( ); }))' *** 第一次抛出调用

如果我将我的模型更改为:

@Model
class SchoolClassSubject {
    var schoolClass: SchoolClass? = nil
    init() {
    }
}
Run Code Online (Sandbox Code Playgroud)

我的保存代码如下:

let schoolClassSubject = SchoolClassSubject()
modelContext.insert(schoolClassSubject)
schoolClassSubject.schoolClass = schoolClass
schoolClass.schoolClassSubjects.append(schoolClassSubject)
Run Code Online (Sandbox Code Playgroud)

但我不想让它成为schoolClass可选schoolClassSubject的,因为它不是现实的。我怎样才能使它不可选并且仍然保存它而不出现给定的错误?

Joa*_*son 3

这个答案是使用 Xcode 15.0 beta 2 编写的,在未来的版本中我认为这个答案将变得无关紧要,我们可以更轻松地处理这个问题

再次强调,您必须使用@Relationship注释才能使关系正常工作,一旦您有了注释,SwiftData 就会为您处理它们。

因此,您不应在init模型的任何方法中包含任何关系属性。

所以将 init 更改SchoolClassSubject

init() {}
Run Code Online (Sandbox Code Playgroud)

(我不知道这是否是一个错误,我们需要一个空的初始化,或者这只是一个奇怪的情况,因为没有其他属性)

然后将按钮操作中的代码更改为

let schoolClassSubject = SchoolClassSubject()
modelContext.insert(schoolClassSubject)
schoolClassSubject.schoolClass = schoolClass
Run Code Online (Sandbox Code Playgroud)

为了澄清上面的代码:

  • 首先创建模型对象的实例
  • 然后将对象插入到模型上下文中
  • 最后将任何关系属性分配给您的对象
  • (节省)