使用Core Data的长时间运行前台操作的最佳实践?

时间:2012-05-03 19:38:34

标签: objective-c ios core-data ios5

我有一个应用程序,在用户明确按下“同步”按钮后从Web导入大量可能的数据,并使用Core Data存储该数据。由于我想显示反馈,并且我不希望用户在发生这种情况时与应用程序的其余部分进行交互,因此按下“同步”按钮会显示“模态”对话框。由于我希望操作立即发生,因此操作在viewDidAppear方法中执行。我确信这是不受欢迎的。

目前这种方法存在许多问题:

  • 一切都发生在主线程中。用户可以获得反馈,因为有一个活动指示器会继续设置动画,但无法指示进度或显示中间消息。这不是正确的做事方式。
    • 但是,我被告知在使用Core Data时,一切都必须使用主线程,因此将工作分解为另一个线程似乎并不简单。
  • 如果应用程序进入后台状态(用户点击主页按钮或iPad进入睡眠状态),那么游戏结束 - 操作就会消失。从文档中我可以清楚地知道为什么会这样。
    • 我知道有“我即将进入后台”你可以处理的事件,但这并不是说我可以在文件下载过程中将代码的执行从一个地方移动到另一个地方。无论我使用什么解决方案,都必须是一个连续的动作,在转换到背景之前和之后都以相同的方式执行。
    • 就用户而言,我希望操作在前台执行。在进行此操作时,他们与应用程序的其他部分进行交互没有任何意义。

我正在阅读有关此问题的Apple文档,但我想问这个是希望找到关于这种特殊需求组合的更简明的指导。感谢。

1 个答案:

答案 0 :(得分:2)

你真的不应该冻结主线程。您仍然可以“禁止”某些UI操作。

作为孩子创建一个单独的上下文,并在那里完成所有工作。完成后(或以特定间隔),将上下文保存到主上下文,并通知主线程进行一些UI更新交互...可能是进度条或其他...

NSManagedContext *backgroundContext = [NSManagedContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroudContext.parentContext = [self mainManagedObjectContext];
[backgroundContext performBlock:^{
    // This block is running in a background thread.
    // Go get your data from the web

    // Call this to push data to the main MOC (either at end, or at intervals)
    [backgroundContext save:&error];

    // When you want to do something on the main thread...
    dispatch_async(dispatch_get_main_queue(), ^{
        // This block is running on the main queue... I can do anything with the UI...
    }];
}];

需要注意的事项......您的mainMOC需要是私有或主队列并发类型。如果您使用的是核心数据模板,它位于应用程序委托中,只需将alloc / init更改为initWithConcurrencyType:NSMainQueueConcurrencyType。

但是,我会建议使用规范的主/父关系。创建一个私有MOC,将其分配给持久存储,然后创建一个主MOC,将其父级设置为该私有MOC。现在,您已准备好使用后台操作处理任何I / O,而不会阻止您的UI。

但是,从网上加载时,请使用上面的模式:创建子MOC,然后将对象加载到主MOC中。

请注意,在“root”MOC调用save之前,数据不会保存到磁盘。