具有关系属性性能问题的核心数据sectionNameKeyPath

Raz*_*van 5 core-data objective-c uitableview nsfetchedresultscontroller ios

我有一个核心数据模型,包括三个实体:
Person,Group,Photo它们之间的关系如下:

  • 人<< ----------->组(一对多关系)
  • 人<------------->照片(一对一)

当我使用NSFetchedResultsControllerin a 执行提取时UITableView,我想Person使用Group's entity name属性对对象进行分组.

为此,我用sectionNameKeyPath:@"group.name".

问题在于,当我使用Group关系中的属性时,在我滚动的时候,NSFetchedResultsController在小批量的20(我有setFetchBatchSize: 20)中提前取出所有内容而不是获取批次tableView.

如果我使用Person实体的属性(比如sectionNameKeyPath:@"name")来创建部分,一切正常:在NSFetchResultsController滚动时加载小批量的20个对象.

我用来实例化NSFetchedResultsController的代码:

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:[Person description]
                                              inManagedObjectContext:self.managedObjectContext];

    [fetchRequest setEntity:entity];

    // Specify how the fetched objects should be sorted
    NSSortDescriptor *groupSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"group.name"
                                                                        ascending:YES];

    NSSortDescriptor *personSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthName"
                                                                         ascending:YES
                                                                          selector:@selector(localizedStandardCompare:)];


    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:groupSortDescriptor, personSortDescriptor, nil]];

    [fetchRequest setRelationshipKeyPathsForPrefetching:@[@"group", @"photo"]];
    [fetchRequest setFetchBatchSize:20];

    NSError *error = nil;
    NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if (fetchedObjects == nil) {
        NSLog(@"Error Fetching: %@", error);
    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"group.name" cacheName:@"masterCache"];

    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}
Run Code Online (Sandbox Code Playgroud)

如果我在"group.name"没有与App的UI交互的情况下创建部分,这就是我在Instruments中得到的: 按关系获取核心数据

如果sectionNameKeyPath为nil,这就是我得到的(在UITableView上滚动一点): 核心数据获取没有任何部分

拜托,有谁可以帮我解决这个问题?

编辑1:

似乎我从模拟器和仪器得到了不一致的结果:当我问这个问题时,应用程序在大约10秒内(由Time Profiler)使用上面的代码在模拟器中启动.

但是今天,使用与上面相同的代码,应用程序在900毫秒内在模拟器中启动,即使它为所有对象进行临时前期提取并且它不会阻止UI.

我附上了一些新的截图: 时间分析器与模拟器 模拟器中的Upfront Fetch无需滚动 使用滚动和小批量提取在Simulator中进行前端提取

编辑2: 我重置模拟器,结果很有趣:执行导入操作并退出应用程序后,第一次运行如下所示: 首先在模拟器重置和新导入后运行 滚动一下后: 首先在模拟器重置,新导入和一些滚动后运行 现在这是第二次运行时发生的事情: 模拟器重置和新导入后再次运行 第五次运行后: 第五次跑

编辑3:第七次和第八次运行应用程序,我得到这个: 第七次跑 第八次跑

Raz*_*van 0

自从我发布这个问题近一年后,我终于找到了导致这种行为的罪魁祸首(在 Xcode 6 中略有变化):

  1. 关于不一致的获取时间:我正在使用缓存,当时我来回打开、关闭和重置模拟器。

  2. 关于所有内容都是预先小批量获取而无需滚动的事实(在 Xcode 6 的 Core Data Instruments 中,情况不再是这样了 - 现在是一次大获取,需要整整几秒钟):

似乎setFetchBatchSize无法正确使用parent/child contexts. 该问题早在 2012 年就已报告过,而且似乎仍然存在http://openradar.appspot.com/11235622

为了解决这个问题,我independent context用 an创建了另一个NSMainQueueConcurrencyType,并将其设置persistence coordinator为与我的另一个正在使用的相同contexts

有关问题#2的更多信息,请访问:/sf/answers/802939231/