核心数据:后台更新 NSManagedObjectContext 在保存时不起作用

Posted

技术标签:

【中文标题】核心数据:后台更新 NSManagedObjectContext 在保存时不起作用【英文标题】:Core Data: Update on background NSManagedObjectContext not working upon save 【发布时间】:2020-06-14 21:56:15 【问题描述】:

我有两个托管对象上下文,我想按照通常的建议将每个用于 fetchupdate

但是,我使用newBackgroundContext() 保存数据的所有尝试都失败了。 performBackgroundTask 也没有工作。

我使用viewcontext 成功保存(下面的代码是成功的),但它违背了具有后台保存功能的目的。另外,这可能会导致未来的表现不佳。

我已经尝试在我的两个上下文中设置automaticallyMergesChangesFromParent = true,但无济于事。

我下面的代码中的CoreDataManager 是一个样板类,用于设置返回persistentContainercontext 对象的惰性变量。

是否有适当的方法在任何地方指出如何处理这个标准问题?

PS:当我尝试使用 newBackgroundContext() 插入大量对象时,它工作正常。更新是唯一的问题——可能是因为它涉及到由viewContext 处理的获取。

PS+: 就此而言,如果我使用newBackgroundContext() 获取并保存两者(仅在下面的函数中,而不是在我的 UI 中),它也可以工作。但我不知道这是否是推荐的方法。

PS++:我还尝试将 newBackgroundContext() 包装在一个惰性 var 下,以免每次都创建一个新的,无论如何都会在 performBackgroundTask 内部发生 - 但这种方法仍然无法保存成功。

class func updateRecord(recordId: String, data: Data)

    let fetchRequest = NSFetchRequest<MyModel>(entityName: "MyModel")
    let context = CoreDataManager.sharedInstance.queryContext  //wrapper for persistentContainer.viewContext which is used to fetch the intended object to update

    do
    
        fetchRequest.predicate = NSPredicate(format: "recordId == %@", recordId)
        let result = try context.fetch(fetchRequest)
        guard let myModel = result.first
        else
        
            throw CoreDataCustomError.ObjectNotFound
        

        myModel.data = data

        try context.save() //works FINE!

        //what DOES NOT work:  try persistentContainer.newBackgroundContext().save() 

        //what DOES NOT work:  
        //persistentContainer.performBackgroundTask  (context) in
        //    context.save()
        //
    
    catch let customErr as CoreDataCustomError
    
        print("Object does not exist in DB: \(customErr)")
    
    catch let err
    
        print("Error saving data \(recordId): \(err)")
    

【问题讨论】:

【参考方案1】:

如果我使用 newBackgroundContext() 来获取并保存两者(就在 下面的功能,不在我的 UI 中),它也可以工作。但我不知道这是否 是推荐的方法

是的,这是正确的方法。

当您在某些上下文中初始化数据时,您必须将其保存在同一上下文中。如果您尝试保存另一个上下文,它将无法正常工作,因为这个其他上下文没有任何更改。

当您使用一个上下文获取一些数据时:

let result = try context.fetch(fetchRequest)

然后你修改它:

myModel.data = data

它仅在此上下文中可见。这意味着如果您尝试保存另一个上下文,它将不会看到模型的更改,并且您的数据也不会被保存。

【讨论】:

以上是关于核心数据:后台更新 NSManagedObjectContext 在保存时不起作用的主要内容,如果未能解决你的问题,请参考以下文章

将 NSManagedObject 更新为核心数据

核心数据 NSManagedObject - ObservedObjects 未更新

当更新版本已经在内存中时,强制核心数据从以前存储的版本刷新 NSManagedObject

核心数据在后台插入大数据

核心数据:更新 NSManagedObject 并选择回退到原始状态

如何使用更新的数据刷新 NSManagedObject - Core Data