【问题标题】:numberOfRowsInSection: method for core data and multiple sectionsnumberOfRowsInSection:核心数据和多个部分的方法
【发布时间】: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;
    }
}

【问题讨论】:

    标签: core-data rows nsfetchedresultscontroller sections


    【解决方案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 不变?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多