问题描述
就我而言,我有一个要更新的 ContactProfile
视图。我认为制作 Contact 实体的副本,编辑副本,然后将副本的属性“粘贴”回原始实体,然后将其保存在 managedobjectcontext
中是个好主意。
到目前为止,我所拥有的代码仅使 tempContact
成为对原始联系人的引用。这是有道理的,因为原始联系人是由 CoreData 生成的类,而不是结构。
解决这个问题的最佳方法是什么?还是我想太多了? @Observedobject
本身是否足以进行编辑,因为它不会保存到数据库中,直到在代码中稍后通过调用 private func saveContext()
函数显式调用它?
struct ContactProfile: View {
@Environment(\.managedobjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Level.sortOrder,ascending: true)],animation: .default)
private var levels: FetchedResults<Level>
@Observedobject var contact: Contact
/// Old code
/// @State private var tempContact: Contact
/// init(contact: Contact){
/// _contact = Observedobject(initialValue: contact)
/// _tempContact = State(wrappedValue: contact)
/// }
///updated code below:
@State private var tempContact = TempContact(firstName: "",lastName: "",birthDate: Date(),picture: nil)
init(contact: Observedobject<Contact>) {
_contact = contact
_tempContact = State(initialValue: tempContact)
tempContact.firstName = contact.wrappedValue.firstName ?? ""
tempContact.lastName = contact.wrappedValue.lastName ?? ""
}
///end of updated code
var body: some View {
Form {
Text("@Observed: \(contact.firstName ?? "UnkNown") \(contact.lastName ?? "UnkNown")")
Text("@State: \(tempContact.firstName ?? "UnkNown") \(tempContact.lastName ?? "UnkNown")")
TextField("Enter name",text: Binding(
get: { self.tempContact.firstName ?? ""},set: { self.tempContact.firstName = $0 }
)
)
[snipped the rest of the normal view code]
此 ContactProfile
是从 ContactsList
访问的,如下所示:
struct ContactsList: View {
@Environment(\.managedobjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Contact.lastName,animation: .default
)
private var contacts: FetchedResults<Contact>
var body: some View {
List {
ForEach(contacts) { contact in
NavigationLink(
destination: ContactProfile(contact: contact)) {
HStack (alignment: .firstTextBaseline) {
Text("\(contact.firstName ?? "UnkNown") \(contact.lastName ?? "UnkNown")")
Text("(\(contact.level?.name ?? ""))").font(.caption).foregroundColor(.gray)
}
}
}
.onDelete(perform: deleteContacts)
}
.listStyle(PlainListStyle())
.navigationTitle("Contacts")
.navigationBarItems(trailing: Button(action: addContact) { Image(systemName: "plus") }
)
}
[snip]
解决方法
处理 Core Data 中的更新很简单:
- 将您的 CoreData 托管对象传递到视图中。
- 设置变量以处理数据编辑输入并将它们设置为 CoreData 对象值的值,类似于您的结构,但在视图中为 @State。
- 验证输入后,将每个属性设置为其对应的@State 变量,如下所示: [您的实体名称].setValue([您的@State 变量],forKey: "[您的属性名称]").
- 将您的实体保存在托管对象上下文中,就像您创建该特定对象时一样。
这将更新您的对象,而不是创建一个新对象。