0

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

我想在显示之前随机洗牌。我已经创建了一个类别,NSArray其中包含一个shuffle可以完美运行的方法,但是调用该方法[self.fetchedResultsController fetchedObjects]没有任何效果,数据保持不变。我假设这是因为fetchedObjectsis readonly,并且我需要制作一份副本。

我已经制作了那个副本,但我遇到的问题是使新阵列与阵列和平共存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];
}

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

4

2 回答 2

2

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

但是如果你真的不需要 FRC 的变化跟踪功能,那么做一个简单的 fetch 会更容易:

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

洗牌结果:

NSArray *shuffledResults = [results shuffle];

shuffledResults在数据源方法numberOfRows...cellForRow.... 然后,您不必保持任何同步。

更新:如果你有部分,那么你需要 FRC 和一个数组数组(1. level 是节号,2. level 是行号)用于洗牌对象。你可以这样填写:

// ... 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”的排序描述符添加到获取请求。)

于 2013-03-12T10:56:37.277 回答
1

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

fetchedObjects会在数组更新的任何时候更新洗牌数组,所以它总是最新的。

于 2013-03-12T12:28:12.387 回答