在后台/前台模式下运行冗长的核心数据删除
Posted
技术标签:
【中文标题】在后台/前台模式下运行冗长的核心数据删除【英文标题】:Lengthy core-data delete run in background/foreground mode 【发布时间】:2014-07-16 09:54:18 【问题描述】:我有一个非常冗长的核心数据删除任务,其中包含 92k 条奇怪的记录,这需要很长时间才能运行。最初它锁定了 UI 线程,所以我试图将调用放在后台线程上。然而,我在模拟器中注意到的是,当我在应用程序后台运行时,此任务停止运行。
我想知道是否有一个快速调整我可以制作代码,以便一旦应用程序在后台运行 10 分钟或允许它们运行多长时间,我的删除将继续运行。
当我开始上课时,我会创建一个后台队列:
backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, nil);
然后什么时候删除我的对象
- (void)queueForDelete:(FlightRecording *)flight
NSError *error = nil;
flight.deleteFlagValue = 1;
[managedObjectContext save:&error];
// Remove flights form Internal table dataStructure
[flightList removeObjectAtIndex:[tmpIndexPath row]];
[[self tableView] deleteRowsAtIndexPaths:@[tmpIndexPath] withRowAnimation:UITableViewRowAnimationFade];
//Queue flight for deletion in the background
dispatch_async(backgroundQueue, ^
NSLog(@"Adding %@ to deletion Queue", flight.getFileName);
[self deleteFlight:flight];
);
[[self tableView] reloadData];
此代码确实使 UI 响应更快,但删除我的对象仍需要大约 5 到 10 分钟(在模拟器中)。我希望用户能够在后台运行应用程序并让删除过程仍在运行,因为无论后台/前台如何,它都会对应用程序的响应能力产生影响。
【问题讨论】:
只是一个观察 - 因为你打电话给deleteRowsAtIndexPaths
,所以没有必要打电话给reloadData
【参考方案1】:
在NSManagedObjectContext
-performBlock:
调用中执行此任务。在具有私有队列并发类型的子上下文上执行此操作。这将为您提供异步处理。
不要在每次调用时保存上下文。
不要在每次调用时更新您的表格视图(reloadData
、delteRowsAtIndexPaths
)。这是一个模型任务。不要更新 UI。
您对tmpIndexPath
的使用是代码异味。这是将模型任务与视图任务混合的另一个迹象。删除一堆对象纯粹是一个模型任务。编写代码,假设不存在 UI 或控制器。
【讨论】:
会开始删除每条记录的单个子上下文吗?还是我一直在使用 preformBlocks 的子单子上下文? 两者都不是。但你很接近。创建一个子上下文。向它发送一个 -performBlock 将遍历所有要删除的对象,然后删除它们。在该块的末尾,保存您的子上下文。检查结果(它可能会成功,除非出现外部错误)。在块内,就在它结束之前,将主线程上的调用(异步)排入队列,以告诉主线程可以更新 UI。 关于 tmpIndexPath => 我所做的是将模型与核心数据分开,因此我手动将数据模型生成到数组中,而不是处理 fetchedResultsController。 tmpIndexPath 是更新对象中的“准备删除”标志,因此当我重新生成模型时,它们会被排除在外以上是关于在后台/前台模式下运行冗长的核心数据删除的主要内容,如果未能解决你的问题,请参考以下文章
React-native-agora 音频仅在后台模式下无法在前台模式下工作(iOS)