我有一个连接到NSFetchedResultsController的表视图,相应的managedObjectContext是self.myDatabase.managedObjectContext:
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.myDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
现在,每当用户刷新页面时,我都会执行以下代码。本质上,我创建一个新线程来加载数据,然后在MOC安全线程上更新/保存新数据:
dispatch_queue_t fetchQ = dispatch_queue_create("fetcher", NULL);
dispatch_async(fetchQ, ^{
NSArray *data = [MyAPI myData];
[document.managedObjectContext performBlock:^{
for (NSDictionary *info in data) {
[MyEntity createOrUpdateGivenInfo:info andManagedObjectContext:self.myDatabase.managedObjectContext];
}
}];
});
dispatch_release(fetchQ);
这很好用:我得到了我的更新,表视图正确地显示了所有内容。唯一的问题是UI没有响应,大概是因为我在主线程上进行了保存/更新。所以我考虑在后台线程上执行此修改:
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init WithConcurrencyType:NSPrivateQueueConcurrencyType];
[backgroundContext setParentContext:self.myDatabase.managedObjectContext];
[backgroundContext performBlock:^{
NSArray *data = [MyAPI myData];
for (NSDictionary *info in data) {
[MyEntity createOrUpdateGivenInfo:info andManagedObjectContext:backgroundContext];
}
[backgroundContext save:nil];
[document.managedObjectContext performBlock:^{
[document updateChangeCount:UIDocumentChangeDone];
}];
}];
然而,虽然UI现在是响应式的,但我在表视图中遇到了很多麻烦:该表显示了一个额外的条目(一个不应该存在的副本),而不是更新现有的条目。我想这可能是因为两个上下文没有同步/合并,但是从阅读之前的SO帖子开始,我被认为我只需要在backContext上调用save,然后在主MOC上调用updateChangeCount。 如果我重新启动应用程序,一切正常 - 直到我再次刷新。
有没有人有任何帮助。我真的开始拉头了。
如果你能解开这个谜团,我会给你啤酒。答案 0 :(得分:2)
UIManagedDocument
为您创建两个上下文:NSPrivateQueueConcurrencyType
的根上下文和NSMainQueueConcurrencyType
的子上下文。
将NSFetchedResultsController
与document.managedObjectContext
挂钩,因为这是主线程的上下文。
在后台线程上自动读取/写入。 UIManagedDocument
负责照顾。你不用担心它。
如果您需要自己做一些繁重的工作,可以创建另一个NSMainQueueConcurrencyType
的托管对象,并将document.managedObjectContext
设为其父级。
我读了你的代码,看起来这就是你做的,这应该有用。这正是我在我的应用程序中的方式。但我看到其他几个人报告重复的条目,NSFetchedResultsController
怀疑存在框架错误。
如果您愿意分享您的项目,我会看看。