UIManagedDocument:如何在后台执行保存

时间:2012-07-05 22:54:20

标签: ios core-data nsfetchedresultscontroller uimanageddocument

我有一个连接到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。 如果我重新启动应用程序,一切正常 - 直到我再次刷新。

有没有人有任何帮助。我真的开始拉头了。

如果你能解开这个谜团,我会给你啤酒。

1 个答案:

答案 0 :(得分:2)

UIManagedDocument为您创建两个上下文:NSPrivateQueueConcurrencyType的根上下文和NSMainQueueConcurrencyType的子上下文。

NSFetchedResultsControllerdocument.managedObjectContext挂钩,因为这是主线程的上下文。

在后台线程上自动读取/写入UIManagedDocument负责照顾。你不用担心它。

如果您需要自己做一些繁重的工作,可以创建另一个NSMainQueueConcurrencyType的托管对象,并将document.managedObjectContext设为其父级。

我读了你的代码,看起来这就是你做的,这应该有用。这正是我在我的应用程序中的方式。但我看到其他几个人报告重复的条目,NSFetchedResultsController怀疑存在框架错误。

如果您愿意分享您的项目,我会看看。