应用程序在删除行时崩溃

时间:2011-05-11 08:54:01

标签: iphone uitableview core-data nsfetchedresultscontroller

我的表用于列出核心数据中的行。一切正常,我已经使用两种类型的数据加载到同一个表视图上。由于范围按钮更改,数据类型会更改。两个范围按钮一个显示已完成的任务,而另一个显示未决的任务我可以在桌面上搜索,更新。虽然只有完整的数据列表是可编辑的并且可以删除,但有时它工作正常,有时会出错,

Serious application error.  An exception was caught from the delegate of 
NSFetchedResultsController during a call to -controllerDidChangeContent:.  *** -
[NSMutableArray insertObject:atIndex:]: index 4 beyond bounds for empty array with 
userInfo (null)

获取结果控制器初始化为,

- (NSFetchedResultsController *)fetchedResultsControllerWithPredicate:(NSPredicate *)predicate{

if (self.fetchedResultsControl != nil) {
    NSLog(@"Here I am outside");

    return self.fetchedResultsControl;

}

为tableview加载单元格的代码如下:

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

CustomCell *cell =(CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    NSArray *topLevelObjects=[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil];
    for (id currentObject in topLevelObjects) {
        if([currentObject isKindOfClass:[UITableViewCell class]]){
            cell=(CustomCell *)currentObject;
            break;
        }
    }

}

[self configureCell:cell atIndexPath:indexPath];
return cell;

}

NSFetchedResultsControllerDelegate调用的更新方法为;

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.listingTable beginUpdates];
NSLog(@"Changed content");
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <  NSFetchedResultsSectionInfo>)sectionInfo
       atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

switch(type) {
    case NSFetchedResultsChangeInsert:
        [self.listingTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                      withRowAnimation:UITableViewRowAnimationFade];
        break;

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

}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"Changed content switch case");
UITableView *tableView = self.listingTable;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [self.listingTable insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationTop];
        break;

    case NSFetchedResultsChangeDelete:
        [self.listingTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(CustomCell *)[tableView  cellForRowAtIndexPath:indexPath]
                atIndexPath:indexPath];

        break;

    case NSFetchedResultsChangeMove:
      [self.listingTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        [self.listingTable insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"Changed Content");
[self.listingTable endUpdates];

}

1 个答案:

答案 0 :(得分:3)

我没有看到任何明显的错误,但在一个tableview中交换两个逻辑表是一个危险的设计,因为你必须非常小心tableview知道它的逻辑表已被更改。

您得到的错误表明tableview使用一个逻辑表的索引配置自己,但实际上是访问第二个逻辑表的数组,该数组更短。

您可以立即解决此问题,密切关注numberOfSectionsnumberOfRowsInSection等方法,以确保在切换逻辑表时这些方法能够正确更新。

最佳设计解决方案是使用两个单独的tableview和各自独立的数据源,然后根据需要将它们交换出来。