核心数据子上下文不是预取关系

我激活了我的应用程序scheme中的核心数据debugging器-com.apple.CoreData.SQLDebug 1 ,并获得了一个名为Category的实体的名为Image的关系实体的以下结果:

主要上下文中的FetchRequest:

 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); } 

控制台日志显示没有错误被执行 – 预期的行为,因为图像关系被设置为预取。

对于儿童情况的相同要求:

 NSManagedObjectContext *privateMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [privateMOC setParentContext:self.mainContext]; [privateMOC performBlock:^{ NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"Category"]; fr.relationshipKeyPathsForPrefetching = @[@"image"]; NSArray *results = [privateMOC executeFetchRequest:fr error:nil]; for (Category *category in results) { NSLog(@"%@",category.image.width); } }]; 

在这种情况下,控制台显示每个图像的Core Data履行错误(其中4个)。 这是一个错误,预期的行为,或者我错过了什么吗?

实验:

我已经在testing应用程序中复制了您的场景,并得出了相同的结论:预取不会在后台线程中发生。 日志:

 ******************************** 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的文档 ,解释了提供预取是为了解决特定的性能问题 。 这是描述如下(我的重点):

预取允许核心数据在单个获取(每个实体)中获取相关对象,而不是随着每个logging的错误被触发而随后访问商店。 例如,给定一个与部门实体有关系的员工实体,如果你提取所有员工,那么每一个打印出他们的姓名和他们所属部门的名称,可能是因为每个单独的Department对象(有关更多详细信息,请参阅Core Data编程指南中的Core Data Performance)。 这可能是一个重大的开销。 您可以通过预取Employee fetch中的部门关系避免这种情况。

从措词上看,这不是提高绩效的必要手段。 这可以解释为什么它没有在后台线程中实现:讨论中描述的性能问题似乎表明涉及UI更新的典型场景。 在我看来,这澄清了这个function的意图。

如果您已经处于后台线程,那么这种性能调整肯定不那么重要,通常的错误机制可以充分地处理必要的优化。 属性relationshipKeyPathsForPrefetching KeyPathsForPrefetching将因此恢复为其默认值,即一个空数组。