关于ios:UIManagedDocument:如何在后台执行保存

UIManagedDocument: How to perform saving in background

我有一个连接到NSFetchedResultsController的表视图,并且对应的managedObjectContext是self.myDatabase.managedObjectContext:

1
2
3
4
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                    managedObjectContext:self.myDatabase.managedObjectContext
                                                                      sectionNameKeyPath:nil
                                                                               cacheName:nil];

现在,每当用户刷新页面时,我都会执行以下代码。本质上,我创建了一个新线程来加载数据,然后在MOC安全线程上更新/保存新数据:

1
2
3
4
5
6
7
8
9
10
11
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没有响应,大概是因为我在主线程上进行了保存/更新。因此,我考虑使用此修改在后台线程上执行该操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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帖子,我被认为是我只需要在backgroundContext上调用save,然后在主MOC上调用updateChangeCount。
如果我重新启动该应用程序,一切将再次正常运行-直到我再次刷新。

有人有帮助吗?我真的开始拔头发。

如果您能解决这个谜团,我会给您喝啤酒。


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

像您一样将NSFetchedResultsController连接到document.managedObjectContext,因为这是您的主线程的上下文。

读/写在后台线程上自动进行。 UIManagedDocument会解决这个问题。您不必担心。

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

我阅读了您的代码,看来这就是您所做的,并且应该可以正常工作。这正是我在应用程序中执行的方式。但是我看到其他人报告NSFetchedResultsController重复条目,怀疑存在框架错误。

如果您愿意分享您的项目,我来看一下。