J'essaie de créer un formulaire de modification qui peut prendre une valeur comme @Binding, la modifier et valider la modification. Dans ce cas, je remplis une liste avec des enregistrements Core Data en utilisant le wrapper de la propriété @FetchRequest. Je veux taper sur une ligne pour naviguer de la liste à la vue détaillée, puis sur la vue détaillée, je veux naviguer vers la vue d'édition.
J'ai essayé de faire cela sans le @Binding et le code se compile mais lorsque je fais une modification, elle n'est pas reflétée sur les écrans précédents. Il semble que je doive utiliser @Binding mais je n'arrive pas à trouver un moyen d'obtenir une instance de NSManagedObject à l'intérieur d'une liste ou d'un ForEach, et de la passer à une vue qui peut l'utiliser comme @Binding.
Vue de la liste
struct TimelineListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
// The Timeline class has an `allTimelinesFetchRequest` function that can be used here
@FetchRequest(fetchRequest: Timeline.allTimelinesFetchRequest()) var timelines: FetchedResults<Timeline>
@State var openAddModalSheet = false
var body: some View {
return NavigationView {
VStack {
List {
Section(header:
Text("Lists")
) {
ForEach(self.timelines) { timeline in
// How to I use the timeline in this list as a @Binding?
NavigationLink(destination: TimelineDetailView(timeline: $timeline)) {
TimelineCell(timeline: timeline)
}
}
}
.font(.headline)
}
.listStyle(GroupedListStyle())
}
.navigationBarTitle(Text("Lists"), displayMode: .inline)
}
} // End Body
}
Vue détaillée
struct TimelineDetailView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@Binding var timeline: Timeline
var body: some View {
List {
Section {
NavigationLink(destination: TimelineEditView(timeline: $timeline)) {
TimelineCell(timeline: timeline)
}
}
Section {
Text("Event data here")
Text("Another event here")
Text("A third event here")
}
}.listStyle(GroupedListStyle())
}
}
Modifier la vue
struct TimelineEditView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State private var newDataValue = ""
@Binding var timeline: Timeline
var body: some View {
return VStack {
TextField("Data to edit", text: self.$newDataValue)
.shadow(color: .secondary, radius: 1, x: 0, y: 0)
.textFieldStyle(RoundedBorderTextFieldStyle())
.onAppear {
self.newDataValue = self.timeline.name ?? ""
}.padding()
Spacer()
}
.navigationBarItems(
leading:
Button(action: ({
// Dismiss the modal sheet
self.newDataValue = ""
self.presentationMode.wrappedValue.dismiss()
})) {
Text("Cancel")
},
trailing: Button(action: ({
self.timeline.name = self.newDataValue
do {
try self.managedObjectContext.save()
} catch {
print(error)
}
// Dismiss the modal sheet
self.newDataValue = ""
self.presentationMode.wrappedValue.dismiss()
})) {
Text("Done")
}
)
}
}
Je devrais mentionner que la seule raison pour laquelle j'essaie de faire ça est que la modale .sheet()
le truc est super bogué.