我可以使用 NSFetchedResultsController 将 n 条记录映射到 1 个表视图行吗?

Posted

技术标签:

【中文标题】我可以使用 NSFetchedResultsController 将 n 条记录映射到 1 个表视图行吗?【英文标题】:May I map n records to 1 table view row with NSFetchedResultsController? 【发布时间】:2013-11-12 23:08:07 【问题描述】:

在我的应用程序中,我使用 Core Data 以及 NSFetchedResultsController。我需要使用 1 个表视图行来显示 9 条记录而不是 1 条记录。所以我自定义了numberOfRowsInSection

方法:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    // Return the number of rows in the section.
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [self numberOfRowsForNumber: [sectionInfo numberOfObjects]];


- (NSInteger)numberOfRowsForNumber:(NSInteger)num

    NSInteger a = num / 9;
    NSInteger b = num % 9;
    return a + (b == 0 ? 0 : 1);

添加第一条记录就OK了。但是当我添加第二条记录时,出现错误:

-[UITableView _endCellAnimationsWithContext:] 中的断言失败,/SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:1330 2013-11-13 06:54:56.217 TestNSFetchedResultsController[2693:a0b] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了异常。无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (1),加上或减去数字从该部分插入或删除的行数(1 插入,0 删除)加上或减去移入或移出该部分的行数(0 移入,0 移出)。与 userInfo (null)

这是否意味着 NSFetchedResultsController 仅支持 1 记录到 1 行的映射?还是有更好的方法来完成它?

【问题讨论】:

您可能需要自定义委托方法,该方法将尝试将项目添加到 tableView 以响应您添加新记录。您可能需要考虑创建与 9 条记录有关系的其他分组实体,并在 fetchedResultsController 中选择它,然后只需自定义 tableView 单元以显示您可以从分组实体关系属性中检索的相关 9 条记录。我会先尝试自定义委托方法,以便它们匹配自定义数据源。 【参考方案1】:

如果您可以使用NSFetchedResultsController 替代方案,那么使用TLIndexPathTools 中的TLIndexPathController 类很容易做到这一点。它将所有五个NSFetchedResultsController 委托方法滚动到一个didUpdateDataModel 方法中,因此通常更易于使用。但更符合您的需要,它提供了一个willUpdateDataModel 委托方法,可让您将获取的托管对象映射到任意数据模型。这是一个将对象映射为九个组的示例:

- (TLIndexPathDataModel *)controller:(TLIndexPathController *)controller willUpdateDataModel:(TLIndexPathDataModel *)oldDataModel withDataModel:(TLIndexPathDataModel *)updatedDataModel

    NSArray *ungroupedItems = updatedDataModel.items;
    NSMutableArray *groupedItems = [NSMutableArray array];
    NSMutableArray *group;
    for (id object in ungroupedItems) 
        if (!group) 
            group = [NSMutableArray arrayWithCapacity:9];
        
        [group addObject:object];
        if (group.count == 9 || object == [ungroupedItems lastObject]) 
            [groupedItems addObject:group];
            group = nil;
        
    
    return [[TLIndexPathDataModel alloc] initWithItems:groupedItems];

无需过多详细介绍 TLIndexPathTools 的工作原理(参见 readme),您可以针对 TLIndexPathDataModel API 编写视图控制器代码。因此,当您进行上述映射时,您的视图控制器只需要知道数据模型中的项目是托管对象的数组。

有几个示例项目值得一试:

    “Core Data”项目演示了 Core Data 集成 “无结果”项目演示了使用上述委托方法在数据模型包含零项时显示“无结果”行。

需要注意的是,TLIndexPathTools 仅设计为可扩展到几千个项目。因此,如果您有一个非常大的数据集,您可能会遇到性能问题。

【讨论】:

【参考方案2】:

我想通了。我只是自定义NSFetchedResultsControllerDelegate的方法。例如,我定义了didChangeObject方法的自定义NSFetchedResultsChangeInsertNSFetchedResultsChangeDelete案例。

感谢@Duncan Groenewald 的回复。

【讨论】:

以上是关于我可以使用 NSFetchedResultsController 将 n 条记录映射到 1 个表视图行吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以同时使用 UIPageViewControllers 吗?

一旦我可以使用 XMPP 列出用户,我如何在这些用户之间实现聊天?

我可以在 ScriptEditor、SharePoint 中使用 Json 吗?

我可以使用啥图表来显示 Html 事件和操作

HTML5 本地存储 - 我可以为每个键存储多个值,如果不能,我可以使用啥替代方案?

我可以从 WPF 窗口获取 HDC 以便我可以使用 Gdi+ API 绘制它吗?