我的managedObjectContext层次结构如下:(PSC)&lt ;-( writerMOC - private)&lt ;-( mainMOC - main)&lt ;-( backgroundMOC - private)
我有一个名为"名称"的NSManagedObject。财产是"香蕉"。
在backgroundMOC中,我使用backgroundMOC.objectWithID获取对象的引用,更改NSManagedObject" name"属于" Apple",然后设置它" syncStatus"属性为1(标记为同步),然后使用以下例程递归保存moc:
func saveManagedContext(moc: NSManagedObjectContext, shouldSync: Bool = true, completion: (() -> Void)? = nil)
{
print("\nSaving managed object context...")
do {
try moc.save()
if let parentContext = moc.parentContext {
parentContext.performBlock {
self.saveManagedContext(parentContext, shouldSync: shouldSync, completion: completion)
}
}
else {
if shouldSync { SyncEngine.sharedInstance.synchronize(shouldPushUpdates: true) }
completion?()
}
print("Finished saving managed object context...")
} catch {
logger.error("\(error)")
}
}
一旦保存了最后一个moc,就会调用一个同步例程,它在backgroundMOC上工作,后者向本地存储查询syncStatus为1的所有对象,同样在backgroundMOC上调用此提取。 / p>
let fetchRequest = NSFetchRequest(entityName: entity.name)
let syncPredicate = NSPredicate(format: "%K == %d", JSONKey.SyncStatus.rawValue, 1)
fetchRequest.predicate = syncPredicate
return try backgroundMOC.executeFetchRequest(fetchRequest) as? [SyncableManagedObject] ?? []
这正确地返回数组中更新的对象,但是,该对象的syncStatus属性等于0,并且其" name"财产仍然设置为" Banana"。
这真的让我很头疼,我觉得我完全理解了managedObjectContext块应该如何工作,但事实证明这是一个很难解决的问题。
更新 这是提示更新的代码。当轻敲单元格时,从主线程调用此方法。
func updateNameForCell(cell: UITableViewCell)
{
///gets the object id from the fetchedResultsController
guard let fruitMetaID = tableController.objectIDForCell(cell) else { return }
let backgroundMOC = CoreDataController.sharedInstance.newBackgroundManagedObjectContext()
backgroundMOC.performBlock {
do {
guard let fruit = (backgroundMOC.objectWithID(fruitMetaID) as? FruitMetaData)?.fruit else {
throw //Error
}
print(fruit.name) // "Banana"
fruit.name = "Apple"
fruit.needsSynchronization() //Sets syncStatus to 1
CoreDataController.sharedInstance.saveManagedContext(backgroundMOC)
}
catch {
//handle error
}
}
}
再次更新 也许我没有正确创造背景。请赐教!
/// The parent to all other NSManagedObjectContexts. Responsible for writting to the store.
lazy var writerManagedObjectContext: NSManagedObjectContext =
{
let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
managedObjectContext.performBlockAndWait {
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
}
return managedObjectContext
}()
lazy var mainManagedObjectContext: NSManagedObjectContext =
{
let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.performBlockAndWait {
managedObjectContext.parentContext = self.writerManagedObjectContext
}
return managedObjectContext
}()
/// The context associated with background syncing..
func newBackgroundManagedObjectContext() -> NSManagedObjectContext
{
let backgroundManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
backgroundManagedObjectContext.performBlockAndWait {
backgroundManagedObjectContext.parentContext = self.mainManagedObjectContext
}
return backgroundManagedObjectContext
}
答案 0 :(得分:0)
保留儿童MOC(主要背景的儿童)充满了问题。我建议为您执行的每个操作创建一个新的子项(aka backgroundMOC)。
如果没有看到所有代码,这看起来就像子上下文不同步一样。
假设您创建的backgroundMOC
将mainMOC
设置为其父级,那么我想知道-objectWithID:
及其返回的内容。
我也想知道你的-performBlock:
电话。在我的脑海中,线程看起来很好,但更好的测试。尝试更改为-performBlockAndWait:
只是为了测试并查看是否存在线程竞争条件。不是永久性的改变,而是将代码部分作为问题的来源消除。