numberOfRowsInSection:核心数据和多个部分的方法

Posted

技术标签:

【中文标题】numberOfRowsInSection:核心数据和多个部分的方法【英文标题】:numberOfRowsInSection: method for core data and multiple sections 【发布时间】:2013-01-13 03:33:25 【问题描述】:

我正在尝试显示一个包含 2 个部分的表格视图。第一部分将始终有 1 行,第二部分将具有与数据点一样多的行。我正在使用 Core Data 和以下 tableView:numberOfRowsInSection: 方法...

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

    if (section == 0) 
        return 1;
     else 
        id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
        return [sectionInfo numberOfObjects];
    

但是,我收到以下错误:

由于未捕获的异常“NSRangeException”而终止应用程序,原因: '* -[__NSArrayM objectAtIndex:]: 索引 1 超出范围 [0 .. 0]'

任何帮助将不胜感激。谢谢。

新 ---------------------------------------------- ----------------------------------

这是相关方法的当前实现:

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

    if (section == 0) 
        return 1;
     else 
        NSUInteger frcSection = section - 1;
        id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:frcSection];
        return [sectionInfo numberOfObjects];
    


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    

    [self configureCell:cell atIndexPath:indexPath];
    return cell;


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath

    if (indexPath.section == 0) 
        cell.textLabel.text = entityOne.name;  //entityOne object passed from previous VC
     else 
        entityTwo = [self.fetchedResultsController objectAtIndexPath:indexPath];
        cell.textLabel.text = entityTwo.name;
    


- (void)controller:(NSFetchedResultsController *)controller
  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex
     forChangeType:(NSFetchedResultsChangeType)type

    NSUInteger frcSectionIndex = 0;
    frcSectionIndex = sectionIndex + 1;

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:frcSectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:frcSectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    


- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath

    UITableView *tableView = self.tableView;

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    

【问题讨论】:

【参考方案1】:

原因是获取结果控制器 (FRC) 只有一个部分 (section #0),您希望将其显示在第二部分 (section #1) 的表格视图。

这是可能的,但您必须在 FRC 部分编号和表格视图部分编号之间进行映射,例如

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

    if (section == 0) 
        return 1;
     else 
        NSUInteger frcSection = section - 1;
        id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:frcSection];
        return [sectionInfo numberOfObjects];
    

cellForRowAtIndexPath 中需要相同的映射。

在 FRC 委托方法 didChangeObjectdidChangeSection 中,您必须在调用表视图方法之前将 1 添加到节号(例如 insertRowsAtIndexPaths)。


添加: configureCell 应如下所示:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath

    if (indexPath.section == 0) 
        cell.textLabel.text = entityOne.name;  //entityOne object passed from previous VC
     else 
        NSIndexPath *frcIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:(indexPath.section - 1)];
        entityTwo = [self.fetchedResultsController objectAtIndexPath:frcIndexPath];
        cell.textLabel.text = entityTwo.name;
    

didChangeObject 这样:

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath

    UITableView *tableView = self.tableView;
    NSIndexPath *tvIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:(indexPath.section + 1)];
    NSIndexPath *tvNewIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row inSection:(newIndexPath.section + 1)];

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[tvNewIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[tvIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:tvIndexPath] atIndexPath:tvIndexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:@[tvIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:@[tvNewIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    

你大概明白了:

当从 FRC 索引路径转到表视图索引路径时,向该部分添加一个。 从表视图索引路径转到 FRC 索引路径时,从该部分中减去一个。

【讨论】:

谢谢。正如您所解释的,我已经能够在 numberOfRowsInSection: 和 didChangeSection: 方法中进行映射。但是,我很难在 cellForRowAtIndexPath: 和 didChangeObject: 方法中进行映射。你能帮我处理这两个映射吗? @AveLeon:如果您将这些功能的当前实现添加到您的问题中,我可以尝试提供帮助。 谢谢。我已经做了。如您所见,我无法使用索引路径更改方法中的节号。 非常感谢!这当然有帮助! 问题:您是否故意在 NSFetchedResultsChangeUpdate 案例中保留 indexPath 不变?

以上是关于numberOfRowsInSection:核心数据和多个部分的方法的主要内容,如果未能解决你的问题,请参考以下文章

ReloadData 不会触发 tableView:numberOfRowsInSection:

对成员 '(_:numberOfRowsInSection:)' 的模糊引用

如何返回 numberOfRowsInSection?

数组未与 tableView(numberOfRowsInSection) 方法连接

numberOfRowsInSection:未在 reloadData 上调用

numberOfRowsInSection 多次调用但 cellForRowAtIndexPath 从未调用