我遇到的问题如下:
我有一个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
我正在排序的属性,但这只会优化查找而不是排序性能。
非常感谢任何想法,谢谢!
答案 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/
并且核心数据编程指南“分批导入”
中也提到了这项技术答案 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];
});