从NSFetchedResultsController中混洗结果

时间:2013-03-12 09:49:18

标签: objective-c core-data random nsarray nsfetchedresultscontroller

我正在使用NSFetchedResultsController从Core Data结构中提取几千个结果并将其显示在UITableView中。我有一些可用的选项,用谓词执行提取并显示更新的数据,例如按关键字搜索,按作者排序等。

我想在显示之前随机随机播放订单。我创建了一个NSArray类别,其shuffle方法运行正常,但在[self.fetchedResultsController fetchedObjects]上调用该方法无效,数据保持不变。我假设这是因为fetchedObjectsreadonly,而且我需要复制。

我已经制作了这个副本,但我遇到的障碍是让新阵列与fetchedObjects阵列和平共存。我可以转到各种详细视图并修改内容,因此我试图确定如何使fetchedObjects和我的shuffledFetchedObjects数组保持同步,即使它们的内容顺序不同。

这是我简单的小shuffle类别:

- (NSArray *) shuffle {
    NSMutableArray *tmp = [NSMutableArray arrayWithArray: self];
    for (int i = [tmp count] - 1; i > 0; i--) [tmp exchangeObjectAtIndex: arc4random() % (i + 1) withObjectAtIndex: i];
    return [NSArray arrayWithArray: tmp];
}

我有什么选择来实现这个目标?

2 个答案:

答案 0 :(得分:2)

无法修改获取的结果控制器(FRC)的fetchedObjects。您可以使用随机索引将FRC行号映射到表视图行号,而不是对提取的对象进行洗牌,反之亦然。

但是如果你真的不需要FRC的更改跟踪功能,那么更容易进行简单的提取:

NSArray *results = [context executeFetch:request error:&error];

洗牌结果:

NSArray *shuffledResults = [results shuffle];

并在数据源方法shuffledResultsnumberOfRows...中使用cellForRow...。 然后你不必保持任何同步。

更新:如果你有部分,那么你需要FRC,并且需要一个数组(1. level是节号,2。对行号进行调整)。你可以像这样填写:

// ... after [frc performFetch:&error] ...
self.dataSource = [NSMutableArray array]; // a NSMutableArray property of your view controller
for (NSUInteger section = 0; section < [[frc sections] count]; section++) {
    NSArray *objects = [[frc sections][section] objects]; // all objects of this section
    [self.dataSource addObject:[objects shuffle]];
}

然后,在cellForRowAtIndexPath中,您可以像这样访问数组:

NSManagedObject *obj = self.dataSource[indexPath.section][indexPath.row];

(一种完全不同的方法是向实体添加属性“randomOrder”,为每个对象分配随机数,并将“randomOrder”的排序描述符添加到获取请求。)

答案 1 :(得分:1)

我设法通过使用shouldShowShuffled布尔值来解决问题,我根据选择的过滤器来打开和关闭。如果它已转为ON,我会显示我的FRC结果副本的结果,这些结果会被洗牌。如果它已转为OFF,我会直接从FRC显示fetchedObjects

我在更新fetchedObjects数组时随时更新混洗数组,因此它始终是最新的。