我有一个简单的用例,其中我有一个核心数据模型,其中具有(具有“时间戳”属性)和与(具有“tagName”属性)的Item
一对一关系。Tag
我想使用 SwiftUI 显示项目列表,并在每一行中显示项目的时间戳和 tag.tagName(如果可用)。
我遇到的问题是,如果我更新与某个项目关联的 tagName,它不会在 SwiftUI 视图中自动刷新。任何更新都会Item
自动刷新,如果我重新启动应用程序,它也会获取更改......但它不会自动发生。
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>
var body: some View {
NavigationView {
List {
Section {
ForEach(items) { item in
VStack (alignment: .leading){
Text(item.timestamp!, formatter: itemFormatter)
if let tag = item.tag, let name = tag.tagName {
Text("Tag: \(name)")
}
}
}
.onDelete(perform: deleteItems)
} header: {
Text("Items")
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
ToolbarItem (placement: .navigationBarLeading) {
Button(action: addTagItem) {
Label("Add Tag", systemImage: "tag")
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button(action: editTagItem) {
Label("Change Tag Name", systemImage: "phone")
}
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
try? viewContext.save()
}
}
private func addTagItem() {
withAnimation {
let newItem = Tag(context: viewContext)
newItem.tagName = "Design"
if let item = items.first {
item.tag = newItem
}
try? viewContext.save()
}
}
private func editTagItem() {
withAnimation {
if let item = items.first, let tag = item.tag {
tag.tagName = "changed"
}
try? viewContext.save() // <-- should update the List, but doesn't
if let item = items.first, let tag = item.tag {
tag.objectWillChange.send() // tried this, doesn't work
}
}
}
}
我添加了工具栏按钮来测试添加新项目、新标签并将第一个项目的标签设置为第一个标签,然后设置一个更改标签名称的场景。前两个函数工作正常,但更改 tagName 不会更新列表视图。
看起来 SwiftUI只@FetchRequest
监听更改Item
。我想这与 which 会做同样的事情类似NSFetchedResultsController
,但我希望 SwiftUI 能够改善这种情况。在我查看的其他问题中,objectWillChange.send
似乎有帮助,但似乎并没有解决我的问题。
无论如何,如果关系属性发生更改,刷新完整列表的最佳方法是什么?
只需使用
@ObservedObject var tag: Tag