0

我有一个连接到 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 帖子,我被引导相信我只需要在 backgroundContext 上调用 save ,然后在主 MOC 上调用 updateChangeCount 。如果我重新启动应用程序,一切都会再次正常 - 直到我再次刷新。

有没有人可以帮忙。我真的开始拔头发了。

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

4

1 回答 1

2

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

像你一样连接你NSFetchedResultsControllerdocument.managedObjectContext,因为那是你的主线程的上下文。

读/写在后台线程上自动发生。UIManagedDocument照顾那个。你不必担心它。

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

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

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

于 2012-07-06T06:44:59.083 回答