代码之家  ›  专栏  ›  技术社区  ›  Douglas Mayle

如何使用NSFetchedResultsController处理节插入?

  •  0
  • Douglas Mayle  · 技术社区  · 17 年前

    我有一个NSFetchedResultsController作为我的数据源,我在自定义UITableViewController中实现了NSFetchedResultsController委托。我使用sectionNameKeyPath将结果集分解为多个部分。

    在我的一个方法中,我向上下文添加了几个对象,所有这些对象都在一个新的部分中。在保存对象时,委托方法被正确调用。事件顺序:

    // -controllerWillChangeContent: fires
    [self.tableView beginUpdates]; // I do this
    
    // -controller:didChangeSection:atIndex:forChangeType: fires for section insert
    [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
    
    // -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath fires many times
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                    withRowAnimation:UITavleViewRowAnimationFade]; // for each cell
    
    // -controllerDidChangeContent: fires after all of the inserts
    [self.tableView endUpdates];  // <--- Where things go terribly wrong!!!
    

    在最后一次调用“endUpdates”时,应用程序总是因以下原因崩溃:

    Serious application error.  Exception was caught during Core Data change processing:
    [NSCFArray objectAtIndex:]: index (5) beyond bounds (1) with userInfo (null)
    

    在某种程度上,表更新似乎与NSFetchedResultsController数据不同步,事情就这样爆发了。我正在关注NSFetchedResultsControllerDelegate上的文档,但它不起作用。正确的方法是什么?

    更新: 我已经创建了一个测试项目来展示这个bug。您可以从以下网址下载: NSBoom.zip

    2 回复  |  直到 17 年前
        1
  •  1
  •   Kendall Helmstetter Gelner    17 年前

    通过追踪应用程序,我注意到首先调用didChangeSection,它插入一个完整的节,然后重复调用didChangeObject。

    问题是在didChangeSection中插入一个完整的节,然后在更新表视图之前将对象添加到同一节中。这基本上是一个重叠更新的情况。。。(即使在开始/结束更新块中也不允许)。

    如果注释掉单个对象插入,则所有操作均有效:

     case NSFetchedResultsChangeInsert:
                [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                 withRowAnimation:UITableViewRowAnimationFade];
                break;
    

    如果您注释掉部分insert:,它就不起作用了-但是我一直没有幸看到INSERTROWSINSSECTIONS起作用,这很可能是因为还没有部分(我确信这就是为什么您要从一开始就插入部分)。您可能需要检测任何一种情况,才能以正确的粒度进行插入。

    总的来说,我在重新加载和插入整个部分时比在插入行时幸运得多,在我看来,在那些正在工作的部分中,表视图似乎非常灵活。您还可以尝试UITableViewRowAnimationNone,它似乎可以更频繁地成功运行。

        2
  •  0
  •   Brain2000    16 年前

    现在,我正在研究NSManagedObjectContextDidSaveNotification观察者方法。这不是NSFetchedResultsControllerDelegate协议的一部分,但您可以注册以接收它。也许只有在我实际调用save时才会调用它,而不是在调用save之前。