我们遇到这个问题,其中不同的线程在相同的记录上看到不同的数据,但具有不同的托管对象上下文(moc)。我们的应用程序在后台同步到服务器API。所有的同步都是在它自己的线程上完成并使用它自己的moc。但是,我们发现当数据在主moc上更新时,数据中的更改未显示在后台moc中。有什么想法会发生什么?这里有一些更详细的信息:我们正在使用像这样的宏中央调度将同步操作放在它自己的线程上:我们已经检查了哪些队列正在运行,而这一切都发生在预期的队列中。
- (void) executeSync; {
dispatch_async(backgroundQueue, ^(void) {
if([self isDebug])
NSLog(@"ICSyncController: executeSync queue:%@ \n\n\n\n\n", [self queue]);
for(id <ICSyncControllerDelegate> delegate in delegates){
[delegate syncController:self];
}
if([ICAccountController sharedInstance].isLoggedIn == YES && shouldBeSyncing == YES) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 300ull * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self executeSync];
});
}
});
}
这是我们如何创建背景moc,我们已经确认它是在后台队列中创建的。
- (NSManagedObjectContext*)backgroundObjectContext {
if (_backgroundObjectContext)
return _backgroundObjectContext;
_backgroundObjectContext = [[NSManagedObjectContext alloc] init];
[_backgroundObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
[_backgroundObjectContext setStalenessInterval:0.0];
return _backgroundObjectContext;
}
我应该补充一点,我们的后台moc正在重新查询数据,那些从该操作返回的记录仍然具有某些字段的旧值。后台moc如何获取主moc已保存的当前数据?我只想通过重新考验来获得这些记录的当前状态。
通过requerying我的意思是: 后台MOC正在执行另一个“查询”以在主moc更改记录后获取“新鲜”数据,但数据具有旧值 - 而不是主moc中看到的更新值。
+ (NSArray *)dirtyObjectsInContext:(NSManagedObjectContext *)moc {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(memberships, $m, $m.category.name == %@ AND $m.syncStatus > %d).@count > 0", MANAGED_CATEGORY_FAVORITES, ManagedObjectSynced];
return [self managedObjectsWithPredicate:predicate inContext:moc];
}
我们非常感谢您的帮助,因为我们一直试图解决这个问题,或者找到一个解决方法,不包括现在放弃我们的线程。
答案 0 :(得分:4)
它应该如何工作 - 实际上,托管对象上下文的一个重要作用是保护您免受其他线程中对数据的更改。想象一下,如果你有一个后台线程修改主线程正在使用的相同对象而没有某种同步方案,那么会造成严重破坏。
阅读Communicating Changes Between Contexts以了解如何将更改从一个上下文合并到另一个上下文中。
答案 1 :(得分:4)
我使用以下代码来监听上下文2的更改,以便上下文1保持最新:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:context1
selector:@selector(contextTwoUpdated:)
name:NSManagedObjectContextDidSaveNotification
object:context2];
它导致在上下文1上调用此方法,并且我调用merge方法:
- (void)contextTwoUpdated:(NSNotification *)notification {
[context1 mergeChangesFromContextDidSaveNotification:notification];
}
这样做的副作用是附加到context1
的任何NSFetchedResultsController都会向其委托发送各种消息,通知它有关更改,
当用户更改对象并且从后面更新用户时,我从未尝试过双向监听 - 我怀疑如果是这种情况你可能必须管理合并,因为它是单向的(并且所有用户驱动) )对我来说,我认为所有更新都是有效的