【问题标题】:exception thrown trying to insert new table row into section尝试将新表行插入部分时抛出异常
【发布时间】:2011-04-24 02:11:55
【问题描述】:

我似乎遇到了一个非常奇怪的问题,该问题仅在尝试将新的 NSManagedObject 插入新部分时发生。基本上我的部分是天,单个单元格与时间相关联。当我将一个对象移动到当前没有与该天关联的另一个对象(表行)的一天时,该表需要创建一个新部分并移动该行。我得到以下结果,而不是正确发生这种情况:

严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。 * -[NSMutableArray removeObjectAtIndex:]: 索引 1 超出界限 [0 .. 0] with userInfo (null)

为当前没有其他对象的一天插入一个新对象似乎工作正常。

问题似乎出在这段代码的某个地方,但我似乎无法弄清楚它有什么问题。 controller:didChangeSection:... 似乎首先使用插入和删除调用,然后使用 NSFetchedResultsChangeMove 调用 controller:didChangeObject:...。所以顺序是:

NSFetchedResultsChangeInsert(在 didChangeSection 中) NSFetchedResultsChangeDelete(在 didChangeSection 中) NSFetchedResultsChangeMove(在 didChangeObject 中)

/**
 Delegate methods of NSFetchedResultsController to respond to additions, removals and so on.
 */

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.plainTableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath
 forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tv = self.plainTableView;

switch(type) {
    case NSFetchedResultsChangeInsert:
        [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(UITableViewCell *)[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

    case NSFetchedResultsChangeMove:
        [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        // Reloading the section inserts a new row and ensures that titles are updated appropriately.
        [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}

- (void)controller:(NSFetchedResultsController *)controller
  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex
     forChangeType:(NSFetchedResultsChangeType)type {
    switch(type) {
    case NSFetchedResultsChangeInsert:
        [self.plainTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [self.plainTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.plainTableView endUpdates];
}

我认为这只是标准模板代码。有谁知道可能出了什么问题?

实际上,在尝试将新行插入已存在的日期时也会发生这种情况,但在为不存在的日期插入新行/对象时不会发生。

【问题讨论】:

    标签: iphone cocoa cocoa-touch uitableview core-data


    【解决方案1】:

    我似乎通过从最新版本的 CoreDataBooks 复制以下代码解决了这个问题:

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

    之前这里的代码是:

        case NSFetchedResultsChangeMove:
            [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;
    

    【讨论】:

    • 是的,reloadSections 行也让我崩溃了。
    【解决方案2】:

    我认为你在这里有一个概念问题。

    controller:didChange... 方法应该调用以响应提取结果控制器 (FRC) 检测到的数据模型的变化。我很确定您的问题是您在更改表之前或不更改基础数据。

    节和行不是表的属性,它们是由 FRC 结构化的数据的属性。如果您需要添加一个部分,您需要先将其添加到数据中,然后让 FRC 委托方法使表保持最新。该表反映了数据模型,而不是相反。

    如果您不这样做,FRC 将报告错误的节数或行数,并导致表格因您看到的错误而崩溃。

    【讨论】:

    • 在查看了似乎可以解决此问题的代码后,看起来最初我没有在 NSFetchedResultsChangeMove 中调用 insertRowsAtIndexPaths。因此,在那 NSFetchedResultsChangeMove 中,该行被删除但没有在其他地方重新插入。 CoreDataBooks 中的评论说“重新加载该部分会插入一个新行并确保标题得到适当更新。”我猜这意味着对 reloadSections 的调用用于插入行,可能在 3.x SDK 中。我确实注意到 CoreDataBooks 在某个时候更新了一条评论,说要使其与 4.x 兼容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    • 2014-04-06
    • 2020-05-01
    • 1970-01-01
    相关资源
    最近更新 更多