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

我在我的应用程序方案中激活了Core Data调试器-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个)执行故障.这是一个错误,预期的行为还是我错过了什么?

解决方法

实验:

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

******************************** 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.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.ZIMAGE FROM ZCATEGORY t0 
CoreData: annotation: sql connection fetch time: 0.0003s
CoreData: annotation: total fetch execution time: 0.0005s for 4 rows.

分析:

根据NSFetchRequest的documentation,解释了提供预取以解决特定的性能挑战.它描述如下(我的重点):

Prefetching allows Core Data to obtain related objects in a single fetch (per entity),rather than incurring subsequent access to the store for each individual record as their faults are tripped. For example,given an Employee entity with a relationship to a Department entity,if you fetch all the employees then for each print out their name and the name of the department to which they belong,it may be that a fault has to be fired for each individual Department object (for more details,see Core Data Performance in Core Data Programming Guide). This can represent a significant overhead. You Could avoid this by prefetching the department relationship in the Employee fetch…

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

如果您已经在后台线程中,那么这种性能调优肯定不那么重要,并且通常的故障机制可以充分地处理必要的优化.因此属性relationshipkeypathsForPrefetching将恢复为其认值,即空数组.

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...