【问题标题】:UIManagedDocument: How to perform saving in backgroundUIManagedDocument:如何在后台执行保存
【发布时间】:2012-07-05 22:54:20
【问题描述】:

我有一个连接到 NSFetchedResultsController 的 Table View,对应的 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 。 如果我重新启动应用程序,一切都会再次正常运行 - 直到我再次刷新。

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

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

【问题讨论】:

  • 您处理背景上下文的总体思路是正确的。请发布您的代码 createOrUpdateGivenInfo:andManagedObjectContext: 哦,是的...还有您的 NSFetchRequest 和 NSFetchedResultsController 的设置——听起来您可能没有正确获取或处理合并。

标签: ios core-data nsfetchedresultscontroller uimanageddocument


【解决方案1】:

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

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

读/写发生在后台线程自动UIManagedDocument 负责这一点。你不必担心。

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

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

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

【讨论】:

    猜你喜欢
    • 2012-01-12
    • 2020-02-28
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    相关资源
    最近更新 更多