核心数据:后台获取,NSFetchedResultsController和排序时间

时间:2011-04-14 09:43:55

标签: sorting core-data background nsfetchedresultscontroller

我遇到的问题如下:

我有一个UITableView我用来自NSFetchedResultsController的数据提供,它从核心数据中检索大约6000行。 fetchBatchSize的{​​{1}}设置为20,如果我不应用任何NSFetchRequest,则提取速度足够快,不会阻止UI线程。

但是,我确实需要按字母顺序显示那些使用以下NSSortDescriptor的行:

NSSortDescriptor

现在,当事情发生变化时,获取操作现在需要大约3秒才能完成,因为6000行正在排序。显然,在这几秒钟内,UI被阻止,用户体验非常糟糕。

我知道我可以在后台线程中执行获取,然后将对象ID传递给主线程,但在这种情况下,我怎样才能在主线程中使用[[[NSSortDescriptor alloc] initWithKey:@"optionText" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] autorelease]; (我也在使用它观察数据的变化)?

我还有NSFetchedResultsController我正在排序的属性,但这只会优化查找而不是排序性能。

非常感谢任何想法,谢谢!

6 个答案:

答案 0 :(得分:3)

如何使用NSFetchRequest的batchSize属性?

  

如果设置非零批量大小,则返回对象集合   当执行获取被分成批次时。当获取时   执行,评估整个请求和所有的身份   匹配记录的对象,但不超过batchSize对象的数据   将一次从持久存储中获取。阵列   从执行请求返回的将是一个代理对象   透明地按需批量故障。 (在数据库方面,这是一个   内存中的光标。)

答案 1 :(得分:1)

我在NSOperation中进行后台批量导入,它使用单独的NSManagedObjectContext。我会定期保存第二个上下文,它会触发通知以更新我的NSFchedchedResultsController连接到的主NSManagedContext。

也许类似的技术可以应用于你的提取

这是一个可可是我女朋友的文章:

http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/

并且核心数据编程指南“分批导入”

中也提到了这项技术

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW1

答案 2 :(得分:0)

使用缓存可能有助于获得更好的性能。

我遇到了同样的问题,并意识到在第一次调用中,fetch需要超过3秒但执行两次获取会立即显示其结果。

答案 3 :(得分:0)

在一个表中显示6000行可能不是用户体验方面的最佳解决方案。也许你之前应该添加一个过滤表。与地址簿中的组类似。如果您设法将每个过滤器选项的行数减少到更易管理的数量,这可能会带来更好的用户体验。这样可以减少加载时间和滚动时间。

我不知道你正在显示什么类型的数据,所以也许除了在一个长列表中显示所有数据之外别无他法。对于人们,您可以为性别和年龄组添加选项。对于汽车,您可以按品牌和型号添加过滤器....

答案 4 :(得分:0)

首先,NSFetchedResultsController通常用在主线程上。并且它不支持背景提取,直到现在Apple发布iOS 6。

因此,当您调用NSFetchedResultController的performFectch时,您必须"阻止"一段时间的主线程。但是我们确实希望时间最短。

(据我所知,你必须为NSFetchedResultController设置一个排序描述符。所以我不确定你是如何在没有设置排序描述符的情况下使它工作的。看一下类引用)

我不确定您是否使用Sqlite Store。如果是这样,我几乎不相信你的排序描述符有效。 (看看核心数据编程指南:故障排除部分)。如果没有,在内存中保留这么多数据不是一个好主意

最后,我们达到了它为何缓慢的程度。这种使用" localizedCaseInsensitiveCompare:"因为比较Unicode字符串会很慢,所以你的获取速度会变慢。 (在WWDC 2010上提到的iPhone核心数据性能)。

与许多其他应用程序一样,您应该根据" optionText"创建一个非Unicode字符串字段/属性。并基于该非Unicode字符串属性进行排序。

答案 5 :(得分:-4)

您是否尝试使用

在后台运行performFetch:方法
[controller performSelectorInBackground:@selector(performFetch) withObject:nil];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    [controller performFetch];
});