Cocoa touch 核心数据:大后台能否在主线程上获取块获取请求?

Cocoa touch 核心数据:大后台能否在主线程上获取块获取请求?,cocoa-touch,ipad,core-data,Cocoa Touch,Ipad,Core Data,我有一个iPad应用程序,核心数据中有相当多的文本数据(约75MB)。每周导入新数据。导入发生在具有自己的NSManagedObjectContext甚至自己的NSPersistentStoreCoordinator的辅助线程上 导入过程包含许多回迁,除了一个回迁外,所有回迁都非常有效,因为它返回大量记录(这可能会稍微优化一些,但实际上并非如此)。不幸的是,在进行大回迁期间,主UI被阻塞(因为它还必须从存储区回迁,回迁被延迟). 我已经在不同点测试了导入过程,以确认它确实位于后台线程上。我仔细

我有一个iPad应用程序,核心数据中有相当多的文本数据(约75MB)。每周导入新数据。导入发生在具有自己的NSManagedObjectContext甚至自己的NSPersistentStoreCoordinator的辅助线程上

导入过程包含许多回迁,除了一个回迁外,所有回迁都非常有效,因为它返回大量记录(这可能会稍微优化一些,但实际上并非如此)。不幸的是,在进行大回迁期间,主UI被阻塞(因为它还必须从存储区回迁,回迁被延迟).

我已经在不同点测试了导入过程,以确认它确实位于后台线程上。我仔细检查了代码,以确保使用带有单独协调器的导入上下文。undomanager为零,导入上下文经常重置


即使使用单独的NSPersistentStoreCoordinator,后台的大型获取请求是否仍可能阻止主线程上的获取请求,或者我是否做错了什么

听起来您已经正确地处理了线程(尽管从技术上讲,您不需要每个线程都有一个新的NSPersistentStoreCoordinator,只要每个线程都有一个NSManagedObjectContext)

你的大回迁听起来像是个问题;您是否查看过NSFetchedResultsController以批处理结果

如果您已经有了,那么您需要找到一些优化查询的方法-您用于大型获取的NSPredicate是什么


另一种方法可能是将文本数据卸载到平面文件中,只将文件名保留在核心数据中——这将减少需要写入的数据量,从而缩短阻塞其他线程的时间


您可以只向NSManagedObject子类添加一个方法,该方法根据请求从文件中获取文本-您的UI不应该知道如何存储文本

后台线程上的操作无法阻止主线程,但它会消耗大量内存,使主线程能够更有效地运行

这听起来像是你的大量背景抓取,“返回大量记录”正在创建一个大的内存中的活动对象的对象图,它正在吞噬你的内存。内存不足会妨碍主线程

使用仪器分析你的记忆以确认

解决方案是在内存中只保留实际的活动、填充的对象,这是绝对必要的。您可以使用较小的获取、作为故障获取、获取属性或作为ManagedObjects获取以及类似的方法来减少内存占用

此外,请确保下载数据的网络操作不会占用内存或占用周期

因为它还必须从商店取货,而且取货延迟

这正是罪魁祸首,因此,根据您的情况,答案可能是肯定的是。具体地说,如果您的大回迁与任何其他回迁发生在同一个存储上,则后续回迁将被阻止,直到第一个回迁完成

在这种情况下,一种策略是使用
returnsObjectsAsFaults=NO
预先获取在大规模获取过程中可能使用的任何对象

即使使用单独的NSPersistentStoreCoordinator,后台的大型获取请求是否仍可能阻止主线程上的获取请求


在这种情况下,它不应该阻塞-但正如您在问题中注意到的,还有其他因素可能导致阻塞。此解决方案有其自身的问题:集成更改,但如果您可以合并这两个协调员,那么它基本上可以正常工作。

您好,谢谢您的回复。我不能使用NSFetchedResultsController,因为我没有填充表,即使如此,主线程上的获取请求也很小。大的获取请求是[NSPredicate predicateWithFormat:@“word IN%@”,wordSet];其中wordset包含NSStrings。请求还会预取关系(而不是预取会使性能降低约20倍)。您不必对表使用NSFetchedResultsController,您可以将其用于任何需要的用途;)但是你是对的,你的问题是在sqlite中进行全文搜索-这永远不会像你现在这样快速:)你需要开始研究倒排索引()或查找表之类的东西-这是一个非常复杂的问题!谢谢你的帮助,但我已经使用了反向索引。然而,我认为我们已经偏离了主题——我需要了解的第一件事是,背景线程上的一个单独的协调器是否可以阻止主线程上的协调器,就像理论上发生的那样,不是;它根本不应该阻塞主线程:)显然,如果不是在核心数据中,SQLite内部也存在某种程度的阻塞。如果SQLite设计得很好,它应该只在短时间内阻塞,但我不知道。谢谢,我将分析内存使用情况,但我应该注意,即使在设备上,后台线程运行时,我也不会收到任何内存警告。我昨天看到了一些代码(),其中在后台线程上使用nsrunlop的rununteldate方法来确保主线程保持平稳运行。我可以试试。在你处理运行循环之前,优化你的抓取和它们的内存使用。