我在我的应用方案中激活了核心数据调试器<p:panel>
,并获得了一个名为Category的实体的以下结果,该实体名为Image:
主要上下文中的FetchRequest:
-com.apple.CoreData.SQLDebug 1
控制台日志显示未满足任何错误 - 自映像关系设置为预取以来的预期行为。
对子级上下文的相同请求:
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"Category"];
fr.relationshipKeyPathsForPrefetching = @[@"image"];
NSArray *results = [self.mainContext executeFetchRequest:fr error:nil];
for (Category *category in results) {
NSLog(@"%@", category.image.width);
}
在这种情况下,控制台显示Core Data为每个图像(其中4个)执行故障。这是一个错误,预期的行为还是我错过了什么?
答案 0 :(得分:4)
我已经在测试应用中复制了您的场景并得出了相同的结论:预取不会在后台线程中发生。记录:
******************************** FOREGROUND **************************************
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZTIMESTAMP, t0.ZTITLE, t0.ZIMAGE FROM ZCATEGORY t0
CoreData: annotation: sql connection fetch time: 0.0004s
CoreData: annotation: Bound intarray values.
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZURL FROM ZIMAGE t0 WHERE t0.Z_PK IN (SELECT * FROM _Z_intarray0)
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0010s for 4 rows.
CoreData: annotation: Prefetching with key 'image'. Got 4 rows.
CoreData: annotation: total fetch execution time: 0.0035s for 4 rows.
******************************** BACKGROUND **************************************
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZTIMESTAMP, t0.ZTITLE, t0.ZIMAGE FROM ZCATEGORY t0
CoreData: annotation: sql connection fetch time: 0.0003s
CoreData: annotation: total fetch execution time: 0.0005s for 4 rows.
根据NSFetchRequest
的{{3}},解释说预提取是为了解决特定性能挑战。它描述如下(我的重点):
预取允许Core Data在单个提取(每个实体)中获取相关对象,而不是在其故障被触发时为每个单独的记录引起对存储的后续访问。例如,给定一个与Department实体有关系的Employee实体,如果您获取所有员工,然后为每个打印出他们的名称和他们所属的部门的名称,可能是因为必须触发故障每个单独的Department对象(有关更多详细信息,请参阅Core Data Programming Guide中的Core Data Performance)。这可能代表了巨大的开销。您可以通过在Employee fetch中预取部门关系来避免这种情况......
从后面的措辞来看,这是不 必要的设备,以提高性能。这可以解释为什么它没有在后台线程上实现:讨论中描述的性能问题似乎表明涉及UI更新的典型场景。在我看来,这澄清了这个功能的意图。
如果您已经在后台线程中,那么这种性能调优肯定不那么重要,并且通常的故障机制可以充分地处理必要的优化。因此,属性relationshipKeyPathsForPrefetching
将恢复为其默认值,即空数组。