CoreData、NSFetchedResultsController 和 performFetch:

Posted

技术标签:

【中文标题】CoreData、NSFetchedResultsController 和 performFetch:【英文标题】:CoreData, NSFetchedResultsController and performFetch: 【发布时间】:2013-03-29 13:07:15 【问题描述】:

我有 450.000 条记录的核心数据。

为了在 uitableview 中显示它,我使用 NSFetchedResultsController。 它可以工作,但有很大的问题。

在 NSFetchedResultsController 启动之前,我们需要调用 执行抓取: 我的情况是这个功能大约需要 2-3 分钟。之后我可以 在 UITable 中显示数据没有任何问题。但是那2-3分钟 杀了我:(

不会那么糟糕,但我还需要在这个表中进行搜索。 因此,对于搜索,我需要更改谓词,调用 performFetch: 和 再等2-3分钟!

有没有办法让 performFetch: 更快? 或者至少有人可以告诉我如何在不调用 performFetch: 的情况下进行搜索?

【问题讨论】:

您的数据是否由 SQLite 支持? 【参考方案1】:

2-3 分钟对于仅获取 450.000 条记录来说绝对是太长了。您是否使用谓词解析字符串?确保您使用了这些优化策略:

通过调整fetchBatchSize 优化您的抓取。 (尝试一些设置,看看哪种设置最适合您的数据类型)。 避免对节标题进行复杂的查询。如果您正在通过关系的某些属性计算部分标题,请重新考虑您的方法。获取保存部分信息的实体并从那里填充每个部分中的行可能会更好。 您是否为搜索和排序所依据的字段编制索引? 尽可能使用模型中定义的获取请求模板。这将大大加快速度。

至于搜索,这是一个对我有用的策略:

仅在几次击键(例如两次)后才对搜索做出反应。 在有效击键后,启动计时器,例如 0.2 秒。只有在计时器触发之前没有再次击键时才开始新的提取。 在后台获取。获取完成后在主线程上重新加载表视图。 维护一组计划的搜索提取。如果计划的提取被 UI 取消(例如,另一个按键),请不要启动它。 不要使用不区分大小写和不区分变音符号的搜索,因为这非常昂贵。相反,如果可行,只需从单词/名称的开头进行搜索。如有必要,按照 Apple 的 WWDC12 视频中的建议,仅使用要在单独实体中搜索的单词(简体、小写)构建索引。

【讨论】:

【参考方案2】:

2-3 分钟对于浏览 450,000 条记录来说是非常长的时间。我怀疑大部分时间都花在了一些 sqlite 调用而不是你自己的代码上。使用 Time Profiler 并查看在 performFetch: 树下花费最多时间的调用。

要查看您的 SQL 是否已优化,请通过将其添加到方案设置中的“启动时传递的参数”来启用 SQLite 日志记录:

-com.apple.CoreData.SQLDebug 1

查看question了解更多详情。

运行您的应用并记下调用 performFetch: 时执行的查询。接下来,阅读有关EXPLAIN QUERY PLAN 的信息。如果 sqlite 是瓶颈,这是您可以使用的最有用的工具。您需要从应用程序(模拟器或设备)中获取 .sqlite 文件,然后在查询中运行 EXPLAIN QUERY PLAN 并查看是否花费了太长时间。如果我不得不猜测,我会说您的查询正在执行全表扫描,而不是使用适当的索引。全表扫描的成本很高。

如果这确实是瓶颈,它还可以帮助您优化搜索。

这里有一些有用的链接。

    How can I improve core data fetch performance on the iPhone? Optimizing Core Data searches and sorts

【讨论】:

以上是关于CoreData、NSFetchedResultsController 和 performFetch:的主要内容,如果未能解决你的问题,请参考以下文章

如何在更新 tableview 时使用搜索栏对我的 NSFetchedResults 数据进行排序,而不会在 fetchedRC.performFetch() 上崩溃?更新

使用 Core Data 在 Swift 3 中保存和检索 MKAnnotations

iOS - 将单元格添加到带有核心数据和 NSFetchedResultsController 的空 UITableView 部分

Array 变化时自动更新 UITableView

合并“NSManagedObjectContextDidSaveNotification”后,NSFetchedResultsController 未显示所有结果

使用没有搜索栏的获取结果控制器过滤表视图?