since a couple of days I try to find a solution for using the same view for both create and edit an CoreData object in SwiftUI.
Assume that we have a CoreData entity called Entry. And it only has one property name: String
Now we have a Main/Master view with a List of all Entry objects. To navigate to the DetailView I use the following code:
List {
ForEach(entires) { entry in
NavigationLink(destination: DetailView(entry: entry)) {
Text(item.name ?? "empty")
}
}
}
In this DetailView I can then edit the existing object:
struct DetailView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) private var viewContext
@State var name: String = ""
@ObservedObject var entry: Entry
init(entry: Entry) {
self.entry = entry
self._name = State(initialValue: entry.name ?? "")
}
var body: some View {
NavigationView {
Form {
Section {
TextField("Name", text: $name)
Button("Save") {
guard name != "" else {return}
entry.name = name
do {
try viewContext.save()
print("saved")
} catch {
print(error.localizedDescription)
}
presentationMode.wrappedValue.dismiss()
}
}
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}.accentColor(.red)
}
.navigationTitle("Entry Name")
}
}
}
But then I need a different view which looks quite the same just for the new entry, since this view does not require a @ObservedObject. This view I access via a simple add button from the Main/Master view and it looks like this:
struct AddView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) private var viewContext
@State var name: String = ""
var body: some View {
NavigationView {
Form {
TextField("Name", text: $name)
Button("Save") {
guard name != "" else {return}
let entry = Entry(context: viewContext)
entry.name = name
do {
try viewContext.save()
print("saved")
} catch {
print(error.localizedDescription)
}
presentationMode.wrappedValue.dismiss()
}
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}.accentColor(.red)
}
.navigationTitle("Add new Entry")
}
}
}
What I don't like here is that I have two views which are 99% equal except that one has the @ObservedObject and the other does not. How can I combine those two views into one? What I would need is something like a @ObservedObject var entry: Entry? where I can keep the Entry optional.