In my case, I have a ContactProfile
view which I want to update. I'd think it would be a good idea to make a copy of the Contact entity, edit the copy and then 'paste' the attributes of the copy back to the original entity and then save it in the managedObjectcontext
.
The code I have so far only makes tempContact
a reference to the original Contact. Which makes sense as the original contact is a class generated by CoreData, not a struct.
What is the best way to get around this? Or am I thinking too much into it? Is the @ObservedObject
itself good enough for editing, since it is not saved to the data base until it is explicitly by calling a private func saveContext()
function later in the code?
So far, I have this code:
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]
This ContactProfile
is accessed from ContactsList
like this:
struct ContactsList: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Contact.lastName, ascending: true)],
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]