CoreData批量删除记录后SwiftUI的List未自动刷新是什么原因?
问题原因
NSBatchDeleteRequest 是CoreData的持久层批量操作,会直接在SQL存储层面执行删除逻辑,不会同步更新当前NSManagedObjectContext内存中已加载的托管对象,也不会触发上下文的对象变更通知。而SwiftUI的@FetchRequest依赖上下文的变更通知触发视图刷新,所以会出现存储层数据已清空,但列表未更新的问题。
解决方案
有两种常用修复方式,可根据你的业务场景选择:
方案1:合并批量删除的变更到当前上下文
执行批量删除时指定返回被删除对象的ID,手动将变更合并到当前上下文,触发@FetchRequest的更新通知,适合数据量较大、需要批量操作高性能的场景:
func deleteAllLocations() { let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Locations") let deleteRequest = NSBatchDeleteRequest(fetchRequest: request) // 配置批量删除返回被删除的对象ID deleteRequest.resultType = .resultTypeObjectIDs do { let result = try myContext.execute(deleteRequest) as? NSBatchDeleteResult guard let deletedIDs = result?.result as? [NSManagedObjectID] else { return } // 把批量删除的变更合并到当前上下文 let changes = [NSDeletedObjectsKey: deletedIDs] NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [myContext]) try myContext.save() } catch let error { errTitle = "Error" errMessage = error.localizedDescription isError = true } }
方案2:直接遍历删除内存中的托管对象
如果数据量不大,不需要用到批量操作的性能优势,可以直接把所有查询到的托管对象逐个删除,上下文会自动触发变更通知,和你单条删除的逻辑完全一致,代码更简洁:
func deleteAllLocations() { do { let allLocations = try myContext.fetch(Locations.fetchRequest()) allLocations.forEach { myContext.delete($0) } try myContext.save() } catch let error { errTitle = "Error" errMessage = error.localizedDescription isError = true } }
内容的提问来源于stack exchange,提问作者Dawy
相关产品推荐
相关产品推荐

