核心数据:后台 NSManagedObjectContext 更新在保存时不起作用
Core Data: Update on background NSManagedObjectContext not working upon save
我有两个托管对象上下文,我想按照通常的建议将每个上下文用于 fetch
和 update
。
但是,我所有试图利用 newBackgroundContext()
保存数据的尝试都失败了。 performBackgroundTask
也没有用。
我使用viewcontext
保存成功(下面的代码是成功的),但是它违背了后台保存功能的目的。另外,它可能会导致未来表现不佳。
我已经尝试在我的两个上下文中设置 automaticallyMergesChangesFromParent = true
,但无济于事。
CoreDataManager
在我下面的代码中是一个样板 class 设置惰性变量返回 persistentContainer
和 context
对象。
是否有适当的方法指示任何地方如何处理这个标准问题?
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)")
}
}
If I use newBackgroundContext() for fetch and save both (just in the
below function, not in my UI), it works too. But I do not know if this
is recommended approach
是的,这是正确的做法。
当您在某些上下文中初始化数据时,您必须将其保存在同一上下文中。如果您尝试保存另一个上下文,它将不起作用,因为这个其他上下文没有更改。
当您使用一个上下文获取一些数据时:
let result = try context.fetch(fetchRequest)
然后你修改它:
myModel.data = data
仅在此上下文中可见。这意味着如果您尝试保存另一个上下文,它不会看到对模型的更改,您的数据也不会被保存。
我有两个托管对象上下文,我想按照通常的建议将每个上下文用于 fetch
和 update
。
但是,我所有试图利用 newBackgroundContext()
保存数据的尝试都失败了。 performBackgroundTask
也没有用。
我使用viewcontext
保存成功(下面的代码是成功的),但是它违背了后台保存功能的目的。另外,它可能会导致未来表现不佳。
我已经尝试在我的两个上下文中设置 automaticallyMergesChangesFromParent = true
,但无济于事。
CoreDataManager
在我下面的代码中是一个样板 class 设置惰性变量返回 persistentContainer
和 context
对象。
是否有适当的方法指示任何地方如何处理这个标准问题?
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)")
}
}
If I use newBackgroundContext() for fetch and save both (just in the below function, not in my UI), it works too. But I do not know if this is recommended approach
是的,这是正确的做法。
当您在某些上下文中初始化数据时,您必须将其保存在同一上下文中。如果您尝试保存另一个上下文,它将不起作用,因为这个其他上下文没有更改。
当您使用一个上下文获取一些数据时:
let result = try context.fetch(fetchRequest)
然后你修改它:
myModel.data = data
仅在此上下文中可见。这意味着如果您尝试保存另一个上下文,它不会看到对模型的更改,您的数据也不会被保存。