在UITableView中移动行时崩溃

时间:2009-11-21 15:26:48

标签: core-data uitableview

以下是例外:

Serious application error.  Exception was caught during 
Core Data change processing: *** -[NSCFArray removeObjectAtIndex:]: 
index (0) beyond bounds (0) with userInfo (null)

以下是相关代码:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 
{
    NSMutableArray *array = [[fetchedResultsController fetchedObjects] mutableCopy];

    id objectToMove = [[array objectAtIndex:fromIndexPath.row] retain];
    [array removeObjectAtIndex:fromIndexPath.row];
    [array insertObject:objectToMove atIndex:toIndexPath.row];
    [objectToMove release];

    for (int i=0; i<[array count]; i++) {
        [(NSManagedObject *)[array objectAtIndex:i] setValue:[NSNumber numberWithInt:i] forKey:JKChecklistRow];
    }
    [array release];
}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
{
    [self.tableView beginUpdates];
}

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

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

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

我怀疑崩溃与Core Data存储与未保存的上下文不同步有关。如果我在-tableView:moveRowAtIndexPath:fromIndexPath:toIndexPath:方法中保存上下文,程序崩溃得更快,但我无法弄清楚原因。

2 个答案:

答案 0 :(得分:1)

如果在移动行时使用节,NSFetchedResultsController和表视图会立即同步。我想这是这堂课的一个错误。因此,根据我的经验,这不是未保存的背景。

其中一个问题是,索引路径在移动后不是最新的,因此该路径上的行数不再正确,这导致“索引超出边界”。假设您有(1,1)的索引并删除(1,1)处的行。索引指向stil(1,1),但第1节的内容不再相同等等。

只需用类似的东西让它可见即可 NSUInteger tableSectionCount = [self.tableView numberOfSections]; NSUInteger frcSectionCount = [[控制器部分]计数]; NSLog(@“tableSectionCount:%d”,tableSectionCount); NSLog(@“frcSectionCount:%d”,frcSectionCount); 你会看到的。

此外,很难找到NSFRC使用NSFetchedResultsChangeMove或NSFetchedResultsChangeUpdate的所有情况。这取决于是否需要重新排序行。 最后,您必须自己为每个特定情况同步tabel视图和NSFRC。最后我花了三天时间才弄明白。

非常有用:http://iphonedevelopment.blogspot.com/2009/11/one-fix-to-nsfetchedresultscontroller.html。我已经向作者发送了更多的调查结果,所以我猜它会有更新。

但是,关键是:关键是让这些部分保持最新状态。

祝你好运! 格尔德

答案 1 :(得分:1)

我明白了。实际上,Jeff LaMarche已经明白了。

拯救我的一些代码:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // In the simplest, most efficient, case, reload the table view.
    if (!self.tableView.editing) 
        [self.tableView reloadData];
}

由于我在表视图本身中移动这些行,因此视图已经反映了这些更改。当我更新我的数据源时,我的代理人会尝试重新排列已经移动的行,从而导致崩溃。