主要上下文中的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); } }];
解决方法
我已经在测试应用程序中复制了您的场景并得出了相同的结论:预取不会在后台线程中发生.日志:
******************************** 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将恢复为其默认值,即空数组.