【问题标题】:Shuffling the results from an NSFetchedResultsController洗牌来自 NSFetchedResultsController 的结果
【发布时间】:2013-03-12 09:49:18
【问题描述】:

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

我想在显示之前随机打乱订单。我用shuffle 方法创建了一个NSArray 类别,该方法运行良好,但在[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];
}

我有哪些选择来实现这一目标?

【问题讨论】:

  • 您真的需要 FRC 吗?如果插入、删除或修改对象,FRC 可用于显示具有自动更新 的表视图。 - 如果插入一个新对象,你期望什么?它应该出现在表格视图的什么位置?
  • 这里没有添加条目的方法,只是删除它们并将它们标记为收藏,然后排序等。
  • 但是你不需要 FRC。只需使用NSArray *results = [context executeFetch:request error:&error]; 获取结果,打乱results 数组并将打乱的数组用作表格视图数据源。
  • 如果我在tableView 上致电reloadData,这还会继续更新吗?我经常这样做。
  • 我不太明白你的最后一个问题。 reloadData查询数据源方法numberOfRows...cellForRow...,这些方法会从打乱后的数组中获取信息。

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


【解决方案1】:

无法修改获取结果控制器 (FRC) 的 fetchedObjects。您可以使用随机 index 将 FRC 行号映射到 table view 行号,反之亦然,而不是打乱获取的对象。

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

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

随机播放结果:

NSArray *shuffledResults = [results shuffle];

并在数据源方法numberOfRows...cellForRow... 中使用shuffledResults。 这样您就不必保持任何同步。

更新:如果你有部分,那么你需要 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”的排序描述符添加到获取请求。)

【讨论】:

  • 所以在这种情况下,无论何时我使用 FRC 执行 fetcb(可能有六个左右的实例具有不同的提取、谓词、排序描述符等)。直接上下文?
  • 所以我遇到了这种方法的问题:节标题。我通过:[[[self.fetchedResultsController sections] objectAtIndex: section] name] 得到这些,而我不能用单独的数组来做到这一点。我怎样才能解决这个问题?
  • @lukech:好的,我已经默默地假设你没有部分。您想随机播放每个部分中的对象吗?然后你需要一个数组数组(每个部分一个)。 - 一种完全不同的方法是向实体添加属性“randomOrder”,为每个对象分配随机数,并将“randomOrder”的排序描述符添加到获取请求中。 - 如果我有更好的想法,我会更新我的答案,或者其他人可能会提出更有用的答案。
  • 最好在每个部分中,是的。
  • 那么我什么时候才能填充那个数组呢?当用户点击“按部分过滤”或其他什么时,或者我会提前做吗?
【解决方案2】:

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

fetchedObjects 数组更新时,我会随时更新改组后的数组,因此它始终是最新的。

【讨论】:

    猜你喜欢
    • 2011-08-26
    • 1970-01-01
    • 2022-11-20
    • 2017-06-24
    • 2019-06-03
    • 2013-12-18
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    相关资源
    最近更新 更多