SwiftUI:删除所有核心数据实体条目后,列表不会自动更新
我知道SwiftUI使用状态驱动渲染。所以我假设,当我删除核心数据实体条目时,包含核心数据元素的列表会立即刷新。 我使用此代码,成功清理实体:SwiftUI:删除所有核心数据实体条目后,列表不会自动更新,swift,core-data,swiftui,Swift,Core Data,Swiftui,我知道SwiftUI使用状态驱动渲染。所以我假设,当我删除核心数据实体条目时,包含核心数据元素的列表会立即刷新。 我使用此代码,成功清理实体: func deleteAll() { let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ToDoItem.fetchRequest() let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequ
func deleteAll()
{
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ToDoItem.fetchRequest()
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
do {
try persistentContainer.viewContext.execute(deleteRequest)
} catch let error as NSError {
print(error)
}
}
func deleteAll()
{
let fetchRequest:NSFetchRequest=ToDoItem.fetchRequest()
let deleteRequest=NSBatchDeleteRequest(fetchRequest:fetchRequest)
让persistentContainer=(UIApplication.shared.delegate为!AppDelegate)。persistentContainer
做{
尝试persistentContainer.viewContext.execute(deleteRequest)
}将let错误捕获为NSError{
打印(错误)
}
}
要使视图中的列表在视觉上为空,我必须在之后离开视图(例如使用“self.presentationMode.wrappedValue.disclease()”),然后再次打开它。好像这些值仍然存储在内存中的某个地方。
这当然不是用户友好的,我确信我只是监督一些立即刷新列表的东西。
也许有人能帮上忙。原因是
执行
(如下所述-注意第一句话)不会影响托管对象上下文,因此所有获取的对象都保留在上下文中,UI表示上下文真正呈现的内容
所以一般来说,在这个批量操作之后,您需要返回到代码(此处未提供)强制同步和重新蚀刻所有内容
API接口声明
例如,它可能是以下方法(scratchy)
//视图中的某处声明
@状态私有变量refreshingID=UUID()
...
//在某个地方呈现获取结果
ForEach(fetchedResults){item in
...
}.id(refreshingID)/<获取结果的唯一id
...
//批量删除某处
尝试context.save()//<最好保存所有挂起的内容
try context.execute(deleteRequest)
context.reset()/
无需强制刷新,这不是一个干净的解决方案
正如你在问题中正确提到的,内存中仍然有元素。解决方案是在执行后使用mergeChanges
更新内存中的对象
这将在“更新内存对象”下详细解释解决方案
在这里,作者提供了对NSBatchDeleteRequest
的扩展,如下所示
extension NSManagedObjectContext {
/// Executes the given `NSBatchDeleteRequest` and directly merges the changes to bring the given managed object context up to date.
///
/// - Parameter batchDeleteRequest: The `NSBatchDeleteRequest` to execute.
/// - Throws: An error if anything went wrong executing the batch deletion.
public func executeAndMergeChanges(using batchDeleteRequest: NSBatchDeleteRequest) throws {
batchDeleteRequest.resultType = .resultTypeObjectIDs
let result = try execute(batchDeleteRequest) as? NSBatchDeleteResult
let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: result?.result as? [NSManagedObjectID] ?? []]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
}
}
以下是有关如何调用它的代码更新:
func deleteAll() {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ToDoItem.fetchRequest()
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
do {
try persistentContainer.viewContext.executeAndMergeChanges(deleteRequest)
} catch let error as NSError {
print(error)
}
}
func deleteAll(){
let fetchRequest:NSFetchRequest=ToDoItem.fetchRequest()
let deleteRequest=NSBatchDeleteRequest(fetchRequest:fetchRequest)
让persistentContainer=(UIApplication.shared.delegate为!AppDelegate)。persistentContainer
做{
尝试persistentContainer.viewContext.executeAndMergeChanges(deleteRequest)
}将let错误捕获为NSError{
打印(错误)
}
}
在此链接下还有更多信息:。谢谢!这种方法效果很好。我希望这也能帮助其他人,因为我在Stackoverflow上找不到这个非常简单的解决方案。:-)在另一个视图中添加记录后,我在更新方面也遇到了同样的问题。因为我只在列表视图中使用上下文来执行删除,所以我重置了上下文并刷新了.onAppear中的ID。我还不完全理解为什么它是必要的,甚至为什么它能工作,但它确实如此,所以谢谢!这不是最好的解决方案,因为.id将重新生成整个列表,而不仅仅是更新更改
extension NSManagedObjectContext {
/// Executes the given `NSBatchDeleteRequest` and directly merges the changes to bring the given managed object context up to date.
///
/// - Parameter batchDeleteRequest: The `NSBatchDeleteRequest` to execute.
/// - Throws: An error if anything went wrong executing the batch deletion.
public func executeAndMergeChanges(using batchDeleteRequest: NSBatchDeleteRequest) throws {
batchDeleteRequest.resultType = .resultTypeObjectIDs
let result = try execute(batchDeleteRequest) as? NSBatchDeleteResult
let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: result?.result as? [NSManagedObjectID] ?? []]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
}
}
func deleteAll() {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ToDoItem.fetchRequest()
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
let persistentContainer = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
do {
try persistentContainer.viewContext.executeAndMergeChanges(deleteRequest)
} catch let error as NSError {
print(error)
}
}