Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SwiftUI:删除所有核心数据实体条目后,列表不会自动更新_Swift_Core Data_Swiftui - Fatal编程技术网

SwiftUI:删除所有核心数据实体条目后,列表不会自动更新

SwiftUI:删除所有核心数据实体条目后,列表不会自动更新,swift,core-data,swiftui,Swift,Core Data,Swiftui,我知道SwiftUI使用状态驱动渲染。所以我假设,当我删除核心数据实体条目时,包含核心数据元素的列表会立即刷新。 我使用此代码,成功清理实体: func deleteAll() { let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ToDoItem.fetchRequest() let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequ

我知道SwiftUI使用状态驱动渲染。所以我假设,当我删除核心数据实体条目时,包含核心数据元素的列表会立即刷新。 我使用此代码,成功清理实体:

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)
    }
}