I have a Thing Core Data entity with a name field. When I display a [Thing] in a List, I want to be able to edit the name inside the child views. Here's the code that does achieve this, but it feels like poor architecture. A ThingView should really be passed thing, not the thing.name!
Instead, I really want to pass the Thing to ThingView, but if I just did that, then updating thing.name would not cause the view to update because Thing is a reference type. Any thoughts on clean design here?
struct ContentView: View {
@ObservedObject var observableAllData: ObservableAllData
var body: some View {
NavigationView{List(observableAllData.allData.things.indices) { index in
NavigationLink(destination:ThingView(
thingName: $observableAllData.allData.things[index].name)) {
Text(observableAllData.allData.things[index].name)}
}
}
}
}
struct ThingView: View {
@Binding var thingName: String
func updateThing() {
thingName = "NEW"
}
var body: some View {
VStack{
Text(thingName)
Button(action: updateThing) { Text("Update it!")}
}
}
}
Edit: Clarification that I want both the ThingView and the ContentView
to update when clicking on "Update it".
You need to pass inside ThingView complete Thing object and use it there instead of its property. Such you will be able update it and save.
So
struct ThingView: View {
@ObservedObject var thing: Thing
func updateThing() {
thing.name = "NEW"
try? thing.managedObjectContext?.save()
}
var body: some View {
VStack{
Text(thing.name)
Button(action: updateThing) { Text("Update it!")}
}
}
}
and in link
NavigationLink(destination:ThingView(
thing: observableAllData.allData.things[index])) {
Update: pattern is the same everything dependent on CoreData entity put into separated view and make it observed that entity.
In your extended question / what's not very polite ;) / put row into separated view
struct ThingRowView: View {
@ObservedObject var thing: Thing
var body: some View {
NavigationLink(destination:ThingView(thing: thing) {
Text(thing.name)}
}
}
}
and call it
NavigationView{List(observableAllData.allData.things.indices) { index in
ThingRowView(thing: observableAllData.allData.things[index])
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With