我有一个iPad应用程序,在Core Data中有相当多的文本数据(大约75MB)。每周导入新数据。导入发生在具有自己的NSManagedObjectContext的辅助线程上,甚至是它自己的NSPersistentStoreCoordinator。
导入过程包含许多提取,所有这些提取都非常有效,除了一个,因为它返回了大量的记录(这可能稍微优化一点,但实际上并不是那么重要。)不幸的是,在此期间进行大量提取,主UI被阻止(因为它也必须从存储中提取并且提取被延迟)。
我已经在各个点测试了导入过程,以确认它确实在后台线程上。我有双重检查代码,以确保使用单独协调器的导入上下文。 undomanager为nil,导入上下文经常重置。
是否有可能即使使用单独的NSPersistentStoreCoordinator,后台的大型提取请求仍然可以阻止主线程上的提取请求,或者我做错了什么?
答案 0 :(得分:2)
后台线程上的操作无法阻塞主线程,但它可能占用大量内存,主线程可以更长时间高效运行。
听起来你的众多背景提取“返回了大量的记录”正在创建一个存储器中活动对象的大对象图,这会占用你的记忆。低内存阻碍了主线程。
使用仪器分析您的记忆以确认。
解决方案是仅将实际的实时填充对象保留在内存中。您可以使用较小的提取,作为故障提取,获取属性或作为managedObjectIDs和类似方法获取以减少内存占用。
此外,请确保下载数据本身的网络操作不会占用内存或周期。
答案 1 :(得分:1)
听起来你已经正在处理正确的线程(虽然你没有技术上需要每个线程一个新的NSPersistentStoreCoordinator,只要每个线程有一个NSManagedObjectContext)。
您的大型提取听起来像问题;你看过NSFetchedResultsController来批量处理结果吗?
如果您已经拥有,那么您需要找到一些优化查询的方法 - 您用于大型提取的NSPredicate是什么?
另一种方法可能是将文本数据卸载到平面文件中,只需将文件名保存在核心数据中 - 这样可以减少需要写入的数据量,从而在较短的时间内阻止其他线程。
您可以向NSManagedObject子类添加一个方法,该子类根据文件请求获取文本 - 您的UI不应该知道如何存储文本!
答案 2 :(得分:0)
因为它还必须从商店获取并且提取被延迟
这正是罪魁祸首,因此,根据您的具体情况,答案可能是明确的是。具体来说,如果您的大型提取与任何其他提取在同一个商店中发生,则后续提取将被阻止,直到第一个提取完成。
在这种情况下,一种策略是使用returnsObjectsAsFaults = NO
预取您在大量获取期间可能使用的任何对象。
是否有可能即使使用单独的NSPersistentStoreCoordinator,后台的大型提取请求仍然可以阻止主线程上的提取请求
在这种情况下,它不应该阻止 - 但正如您在问题中指出的那样,还有其他因素会导致阻塞。这个解决方案有自己的问题:集成更改,但是如果你可以合并两个协调器,那么它就可以正常工作。