SwiftUI调用clear函数后ItemView未刷新问题求助
问题:调用clear函数后ItemView未自动刷新
调用clear函数后,CoreData的增删操作都正常执行,但ItemView不会自动刷新,必须关闭并重新打开History视图才能看到新增的"Clear"记录。不清楚问题出在哪,求解决思路,是否需要添加.onAppear()?
HistoryView 代码
import SwiftUI struct HistoryView: View { @Environment(\.MOC) private var viewContext var card: FetchedResults<Card>.Element var body: some View { ScrollView { VStack() { // Something here! Group { // Something here! HStack() { // Something here! Button(action: { clear() }, label: { Text("Clear") }) } } VStack() { ForEach(card.elementArray) { element in ItemView(element: element) Divider() } } } } } private func clear() { CoreData.shared.clearHistory(card: card, context: viewContext) } } struct ItemView: View { var element: FetchedResults<Element>.Element var body: some View { HStack() { Text(element.date!, format: .dateTime.day(.twoDigits).month(.twoDigits)) Spacer() if element.designation == "Create" { Text("Create") } // Something here! else if element.designation == "Clear" { Text("Clear") } } } } extension Card { public var elementArray: [Element] { let set = element as? Set<Element> ?? [] return set.sorted { $0.date! > $1.date! } } }
CoreData 管理器的 clearHistory 函数
func clearHistory(card: Card, context: NSManagedObjectContext) { card.elementArray.forEach { context.delete($0) } let element = Element(context: context) // Something here! element.designation = "Clear" element.card = card save(context: context) }
解决思路
问题本质:SwiftUI的
ForEach需要能被监听的数据源才会触发视图刷新。你当前用的card.elementArray是自定义计算属性,返回的是普通数组——即便CoreData里的element集合发生变化,这个计算属性的变动无法被SwiftUI感知,自然不会刷新视图。最优修复方案:直接用CoreData的
FetchedResults驱动ForEach,替代自定义数组:- 给HistoryView添加针对当前Card关联Element的FetchRequest:
@FetchRequest private var elements: FetchedResults<Element> init(card: FetchedResults<Card>.Element) { self.card = card _elements = FetchRequest<Element>( sortDescriptors: [NSSortDescriptor(keyPath: \Element.date, ascending: false)], predicate: NSPredicate(format: "card == %@", card) ) } - 替换原有的ForEach数据源:
ForEach(elements) { element in ItemView(element: element) Divider() }
这样CoreData的数据变化会自动通知
FetchedResults,进而触发SwiftUI视图刷新,不需要手动添加.onAppear()。- 给HistoryView添加针对当前Card关联Element的FetchRequest:
为什么自定义数组不行:计算属性
elementArray每次访问都会生成新数组,即便内容变化,它既不是@Published/Observable类型,也不是CoreData自带的可监听集合,SwiftUI无法追踪其变化。备选方案(不推荐):如果一定要保留
elementArray,可以让Card遵循ObservableObject,并在element集合变动时发送objectWillChange通知,但这种做法比直接用FetchRequest繁琐且可靠性更低。
内容的提问来源于stack exchange,提问作者Alexnnd
相关产品推荐
相关产品推荐

