提问人:AAV 提问时间:7/9/2020 最后编辑:AAV 更新时间:8/23/2022 访问量:8562
核心数据对象更改的 SwiftUI 更新视图
SwiftUI update view on core data object change
问:
我遇到的问题是,当我从工作表视图更新核心数据资产对象时,更改不会反映在 AssetListView 的 UI 中。(请注意,从工作表视图插入新对象会刷新 AssetListView 的 UI。删除工作表视图中的对象也会刷新 AssetListView 的 UI) 唯一不起作用的操作是更新。
当核心数据对象发生变化时,如何使 AssetListView 发生变化?
我有以下 SwiftUI 代码,显示了来自 CoreData FetchRequest 的资产列表:
struct AssetListView: View {
@State private var showingSheet = false
@State private var selectedAssetId: NSManagedObjectID?
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Asset.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Asset.allocationPercentage, ascending: false)]) var assets: FetchedResults<Asset>
var body: some View {
VStack {
Form {
ForEach(assets, id: \.self) { asset in
Section {
AssetRowView(asset: asset)
.onTapGesture {
self.selectedAssetId = asset.objectID
self.showingSheet = true
}
}
}
}
}
.navigationBarTitle("Assets").sheet(isPresented: $showingSheet ) {
EditAssetView(assetId: self.selectedAssetId!)
.environment(\.managedObjectContext, self.moc)
}
}
}
}
这是一个编辑屏幕,我将其呈现为 SwiftUI 工作表:
struct EditAssetView: View {
var assetId: NSManagedObjectID
@Environment(\.presentationMode) var presentationMode
@State private var name = ""
@State private var description = ""
@Environment(\.managedObjectContext) var moc
var asset: Asset {
moc.object(with: assetId) as! Asset
}
var body: some View {
NavigationView {
Form {
Section {
TextField("Name", text: $name)
TextField("Description", text: $description)
}
}
.navigationBarTitle(Text("Edit Asset"), displayMode: .inline)
.navigationBarItems(leading: Button("Cancel") {
self.presentationMode.wrappedValue.dismiss()
}, trailing: Button("Done") {
self.presentationMode.wrappedValue.dismiss()
self.asset.name = self.name
self.asset.assetDescription = self.description
try? self.moc.save()
}
)
}
.onAppear {
self.name = self.asset.name
self.description = self.asset.assetDescription
}
}
}
下面是 AssetRowView 的代码:
struct AssetRowView: View {
var asset: Asset?
var body: some View {
HStack {
Text(asset.name)
Text(asset.assetDescription)
}
}
}
答:
28赞
Asperi
7/9/2020
#1
尝试观察(原因是-aAsset
NSManagedObject
ObservableObject
)
struct AssetRowView: View {
@ObservedObject var asset: Asset // << here !!
var body: some View {
HStack {
Text(asset.name)
Text(asset.assetDescription)
}
}
}
如果这还不够,可能还需要将按钮操作更新为Done
}, trailing: Button("Done") {
self.asset.objectWillChange.send() // << here !!
self.asset.name = self.name
self.asset.assetDescription = self.description
try? self.moc.save()
// better do this at the end of activity
self.presentationMode.wrappedValue.dismiss()
}
评论
2赞
AAV
7/10/2020
谢谢!只是让它 ObservedObject 起作用了。不需要调用 objectWillChange.send()
0赞
foolbear
4/7/2021
如果UI元素来自关系,如何更新?例如,班级<->>学生,一个班级有一些学生。在班级列表视图中,每个班级单元格都显示班级名称和学生人数。点击班级单元格时,可以编辑班级并添加/删除学生。学生更改后,如何更新班级单元格?
3赞
zdravko zdravkin
3/21/2021
#2
我所做的是将核心数据对象传递为:
@ObservedObject var toDo: FetchedResults<ToDoModelCoreData>.Element
从我的提取结果
@FetchRequest var todoFetchRequest: FetchedResults<ToDoModelCoreData>
这将确保 swiftUI 视图在 coredata 时更新
2赞
spnkr
10/13/2021
#3
添加到核心数据对象是有效的,但您可能需要滚动列表才能看到更改。具体取决于您设置谓词、托管对象和提取请求的方式。@ObservedObject
在任何进程编辑结束时添加 NSManagedObject 可以解决此问题。foo.objectWillChange.send()
0赞
Florian Cremer
6/23/2022
#4
就我而言,我需要在编辑工作表中的项目后触发对列表视图的更新。 解决方案是在 DidDismiss 处理程序中对父 ManagedObject 调用 objectWillChange.send() 方法。
.sheet(item: $selectedChildItem, onDismiss: editViewDidDismiss) { childItem in
EditItemDetailsView(item: childItem)
}
private func editViewDidDismiss(){
self.parentObject.objectWillChange.send()
}
评论