3

我有一个应用程序,它会在用户明确按下同步按钮后从网络上导入大量数据,并使用 Core Data 存储这些数据。因为我想显示反馈并且我不希望用户在发生这种情况时与应用程序的其余部分进行交互,所以按下同步按钮会弹出一个模态对话框。由于我希望该操作立即发生,因此该操作在 viewDidAppear 方法中执行。我敢肯定,这是不赞成的。

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

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

我正在阅读有关此内容的 Apple 文档,但我提出此问题是希望找到有关此特定需求组合的更简洁的指导。谢谢。

4

1 回答 1

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 需要是私有或主队列并发类型。如果您使用的是应用程序委托中的 Core Data 模板,只需将 alloc/init 更改为 initWithConcurrencyType:NSMainQueueConcurrencyType。

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

尽管如此,当从 web 加载时,使用上面的模式:创建一个子 MOC,然后将对象加载到主 MOC。

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

于 2012-05-08T15:40:25.707 回答