SwiftUI - 将 @Binding 与核心数据 NSManagedObject 一起使用? [英] SwiftUI - Use @Binding with Core Data NSManagedObject?
问题描述
我正在尝试制作一个编辑表单,该表单可以将值作为 @Binding 进行编辑,然后提交更改.在这种情况下,我使用 @FetchRequest 属性包装器填充包含核心数据记录的列表.我想点击一行从列表导航到详细信息视图,然后在详细信息视图上导航到编辑视图.
I'm trying to make an edit form that can take a value as a @Binding, edit it, and commit the change. In this case, I'm populating a list with Core Data records using the @FetchRequest property wrapper. I want to tap on a row to navigate from the List to a Detail view, then on the Detail view I want to navigate to the Edit view.
我尝试在没有 @Binding 的情况下执行此操作,代码将编译,但是当我进行编辑时,它不会反映在之前的屏幕上.似乎我需要使用@Binding,但我无法找到一种方法来在 List 或 ForEach 中获取 NSManagedObject 实例,并将其传递给可以将其用作 @Binding 的视图.
I tried doing this without the @Binding and the code will compile but when I make an edit, it is not reflected on the previous screens. It seems like I need to use @Binding but I can't figure out a way to get a NSManagedObject instance inside of a List or ForEach, and pass it to a view that can use it as a @Binding.
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
}
详细视图
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())
}
}
编辑视图
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")
}
)
}
}
我应该提到,我什至尝试这样做的唯一原因是因为模态 .sheet()
东西是超级错误的.
I should mention, the only reason I'm even trying to do this is because the modal .sheet()
stuff is super buggy.
推荐答案
@Binding
仅适用于结构体.
但 CoreData 结果是对象(NSManagedObject
采用 ObservableObject
).您需要使用 @ObservedObject
来注册更改.
But CoreData result are Objects (NSManagedObject
adopting ObservableObject
). You need to use @ObservedObject
to register for changes.
这篇关于SwiftUI - 将 @Binding 与核心数据 NSManagedObject 一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!