UITableView行删除崩溃的应用程序

时间:2014-04-21 01:30:08

标签: ios objective-c cocoa-touch uitableview core-data

我有一个基于Core Data的表视图,它有一个简单的删除方法。它是直接的代码,可以在无数的教程中找到,但是,它使用以下消息崩溃应用程序:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

删除方法如下:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{


    if (editingStyle == UITableViewCellEditingStyleDelete) {

        // get garden to delete, delete it through Core Data


        Garden *gardenToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"Garden name: %@", gardenToDelete.gardenName);

        [self.managedObjectContext deleteObject:gardenToDelete];
        [self.managedObjectContext save:nil];

        [self.tableView beginUpdates];

        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];

        [self.tableView endUpdates];
        }
}

我花了几个小时重新安排代码,移除beginUpdateendUpdate来电,检查其他解决方案。非常感谢帮助。

3 个答案:

答案 0 :(得分:0)

您只需要从NSFetchedResultsController中删除对象,假设您已按照docs中的说明实现了委托方法,则提取的结果控制器将更新表格视图。您不应该触摸表格视图行,NSFetchedResultsControllerDelegate会完成所有这些操作。

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

  if (editingStyle == UITableViewCellEditingStyleDelete) {

      // deleting cell from fetched results contoller

      Garden *gardenToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
      NSLog(@"Garden name: %@", gardenToDelete.gardenName); 
      [self.managedObjectContext deleteObject:gardenToDelete];
      [self.managedObjectContext save:nil];
  }
}

答案 1 :(得分:0)

您是否实施了这些方法:

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

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

// my comment: mapIndexPathFromFetchResultsController function, I just use to get indexPath. You can remove it 
indexPath = [self mapIndexPathFromFetchResultsController:indexPath];
newIndexPath = [self mapIndexPathFromFetchResultsController:newIndexPath];

switch(type) {
    case NSFetchedResultsChangeInsert:
    {
        [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    }

    case NSFetchedResultsChangeDelete:
    {
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    }

    case NSFetchedResultsChangeUpdate:
    {
        UITableViewCell *cell;
        cell = [tableView cellForRowAtIndexPath:indexPath];
        if (cell != nil)
        {
            // my comment: just use the same with cellForRowAtIndexPath
            // - (void)syncViewConfigureCell:(UITableViewCell *)cell {
            // cell.textLabel.text = @""; etc. }
            [self syncViewConfigureCell:cell];
        }
        break;
    }

    case NSFetchedResultsChangeMove:
    {
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    }
}
    }


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

    case NSFetchedResultsChangeDelete:
        [self.tableView 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.tableView endUpdates];
    }

答案 2 :(得分:0)

您是否使用- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section的返回值实施NSFetchedResultsController?保存后,self.fetchedResultsController将刷新,但请确保tableView返回值的所有dataSource都依赖于self.fetchedResultsController