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

Posted

技术标签:

【中文标题】具有多个 NSFetchedResultsControllers 的 UITableView 导致断言失败【英文标题】:UITableView with multiple NSFetchedResultsControllers causing Assertion failure 【发布时间】:2011-01-12 12:16:02 【问题描述】:

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

在插入、更新...表时,我从 NSFetchedResultsController -controllerDidChangeContent 收到 Assertion failure

我的猜测是 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 以及这样做是否正确?可能还有使用多个 nsfetchedresultscontroller 和一个 uitableview 的任何示例。

【问题讨论】:

【参考方案1】:

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

随着每个控制器进入以下功能

(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>];

【讨论】:

感谢您节省时间 ;) newIndexPath 的一个小错误。应该是[NSIndexPath indexPathForRow:newIndexPath.row inSection:&lt;add correct section&gt;]【参考方案2】:

我不确定它是 FetchedResultController。

insert 和 delete 行调用会在某些时候要求 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 等待单元格的绘制,直到您给出“确定”。

如果不是上述情况,这里是我通常如何处理 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()。 这样可以很容易地确定正在处理的部分以及它的作用。

【讨论】:

以上是关于具有多个 NSFetchedResultsControllers 的 UITableView 导致断言失败的主要内容,如果未能解决你的问题,请参考以下文章

如何按创建 UITableViewCell 时计算的值对 UITableView 进行排序?

启动 Core Data 应用程序时在后台配置 NSFetchedResultsController

使用多个数据库各自具有一个模式,还是使用一个数据库具有多个模式更好?

将具有多个表的 Access 数据库导出到具有多个工作表的 Excel

在具有分页的单个模型查询代码点火器中获取具有多个条件的多个连接结果

将具有多个键的 Python 字典映射到具有多个匹配键的列的数据框中