带有多个NSFetchedResultsControllers的UITableView导致断言失败

时间:2011-01-12 12:16:02

标签: xcode uitableview ios nsfetchedresultscontroller

我有一个包含3个部分的UITableView,每个部分都通过唯一的NSFetchedResultsController提供。

在插入,更新...表格时,我从 NSFetchedResultsController -controllerDidChangeContent 中获得断言失败

我的猜测是下面的方法中的indexPaths的问题,因为每个控制器只有一个部分(0),而第0部分中的控制器不会发生故障。

- (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath
{
    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [[self atableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationLeft];
            break;
        case NSFetchedResultsChangeDelete:
            [[self atableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
            break;
        case NSFetchedResultsChangeUpdate:
            [self configureCell:(DashboardViewCell *) [[self atableView] cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
        case NSFetchedResultsChangeMove:
            [[self atableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [[self atableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    } 
}

所以我的问题是,我如何确定正在处理哪个控制器(来自哪个部分)并相应地修改indexPath,如果这是正确的方法呢?可能有任何使用几个nsfetchedresultscontrollers和一个uitableview的例子。

2 个答案:

答案 0 :(得分:3)

所以我的猜测实际上是正确的:

当每个控制器进入以下功能

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

除了为第0部分设置的控制器之外,每个控制器的indexPath都不正确。

每个控制器只有一个部分 - 在我的情况下为0,但更重要的是,这些部分与表部分不对应。

所以我目前实现的解决方法(不太好,可能会返工)是检查控制器的cacheName,并根据修改indexPath / newIndexPath的部分

类似的东西:

if([[controller cacheName] isEqualToString:@"sectionX"])
{
  indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
  newIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
}

答案 1 :(得分:0)

我不确定它是否为FetchedResultController。

插入和删除行调用将在某一时刻要求tableView重新加载,然后它将询问委托和数据源方法numberOfRowsInSection,cellForRowAtIndexPath等。

可能发生的是模型和tableView不同步,导致控制器发出警告。

    [tableView beginUpdates];

     if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSMutableDictionary *item = [self.itemList objectAtIndex:indexPath.row];
    // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.itemList removeObjectAtIndex:indexPath.row];      

}   
    [tableView endUpdates];

尝试类似这样的事情,其中​​包含对tableView和底层模型的所有更改 beginUpdates和endUpdates。这些将导致tableView等待单元格的绘制,直到你给出'OK'。

如果以上情况并非如此,那么我通常会在tableView中处理多个部分。

在标题中,您为部分声明了typedef枚举;

typedef enum {

    SectionTypeName,
    SectionTypeAge,
    SectionTypeSkills,

} SectionType;

//in the implementation

switch (indexPath.section) {
    case SectionTypeName:
        //do thing in the name section
        break;
    case SectionTypeAge:
        //do thing in the name section
        break;
    case SectionTypeSkills:
        //do thing in the name section
        break;          
    default:
        break;
}

我几乎在每个tableView委托/数据源方法中都有switch()。 这样可以很容易地确定正在处理哪个部分以及它的作用。