我有一个应用程序,在用户明确按下“同步”按钮后,它可能会从网络导入大量数据,并使用 Core Data 存储这些数据。由于我想显示反馈并且我不希望用户在发生这种情况时与应用程序的其余部分进行交互,因此按下“同步”按钮会弹出一个模态对话框。由于我希望操作立即发生,因此操作在 viewDidAppear 方法中执行。我敢肯定这是不受欢迎的。
目前这种方法存在很多问题:
- 一切都发生在主线程中。用户会得到反馈,因为有一个事件指示器会继续显示动画,但无法指示进度或显示中间消息。这不是做事的正确方法。
- 但是,有人告诉我,在使用 Core Data 时,一切都必须使用主线程,因此将工作分解到另一个线程似乎并不简单。
- 如果应用程序进入后台状态(用户按下主页按钮或 iPad 进入休眠状态),则游戏结束 - 操作终止。从文档中我很清楚为什么会这样。
- 我知道您可以处理“我即将进入后台”事件,但我无法在文件下载过程中将代码的执行从一个地方移动到另一个地方。无论我使用什么解决方案,都必须是一个连续的 Action ,在进入/离开后台之前和之后以相同的方式执行。
- 就用户而言,我希望操作在前台执行。在此操作进行期间,他们与应用程序的其他部分进行交互是没有意义的。
我正在阅读关于此的 Apple 文档,但我提出这个问题是希望找到关于这种特定需求组合的更简洁的指导。谢谢。
最佳答案
你真的不应该卡住主线程。您仍然可以“禁止”某些 UI 操作。
创建一个单独的上下文,作为一个 child ,并在那里完成你的所有工作。完成后(或者每隔一段时间),将上下文保存到主上下文中,并通知主线程做一些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 需要是私有(private)的或主队列并发类型。如果您使用的是核心数据模板,它位于应用程序委托(delegate)中,只需将 alloc/init 更改为 initWithConcurrencyType:NSMainQueueConcurrencyType。
但是,我建议使用规范的主/父关系。创建一个私有(private) MOC,将其分配给持久存储,然后创建一个主 MOC,将其父级设置为该私有(private) MOC。现在您已准备好通过后台操作处理任何 I/O,而不会阻塞您的 UI。
仍然,当从网络加载时,使用上面的模式:创建一个子 MOC,然后将对象加载到主 MOC。
请注意,直到“root”MOC 调用 save 时,数据才会保存到磁盘。
关于objective-c - 使用核心数据的长时间运行的前台操作的最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10438218/