Same view for both create and edit in SwiftUI

Viewed 219

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.

0 Answers
Related