UITableView deleteRowsAtIndexPath在删除最后一条logging时崩溃

当我从UITableView删除最后一个logging时遇到以下错误。

由于未捕获的exception“NSInternalInconsistencyException”而终止应用程序,原因是:“无效的更新:第0节中的行数无效。更新(3)之后现有节中包含的行数必须等于该节中包含的行数(1)加上或减去从该部分插入或删除的行数(插入1个,删除1个),加上或减去移入或移出该部分的行数(0移入,0移入出)。”

我的目标是显示“找不到logging”,如果表格数组是空的。

这是我使用的代码。 当我从表格数组中删除最后一个logging的应用程序崩溃。 如何重新加载表格并显示“No Record Found”标签?

 // Customize the number of rows in the table view. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if ([idArray count]==0) { return 3; } else { return [idArray count]; } } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"array count %d",[idArray count]); if ([idArray count] == 0) { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.textLabel.textAlignment = UITextAlignmentCenter; tableView.userInteractionEnabled = NO; self.navigationItem.leftBarButtonItem.enabled = NO; NSUInteger row = [indexPath row]; switch (row) { case 0: cell.textLabel.text = @""; break; case 1: cell.textLabel.text = @""; break; case 2: cell.textLabel.text = @"No Records Found"; break; default: break; } return cell; } else { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } tableView.userInteractionEnabled = YES; self.navigationItem.leftBarButtonItem.enabled = YES; // Set up the cell identify *idItems = [idArray objectAtIndex:indexPath.row]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"dd MMM,yyyy"]; NSString *dateStr = [formatter stringFromDate:idItems.Date]; UIImageView *accDis = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Arrow.png"]]; cell.accessoryView = accDis; self.idTableView.separatorColor = [UIColor colorWithRed:150.0/255.0 green:150.0/255.0 blue:150.0/255.0 alpha:1]; cell.textLabel.textColor = [UIColor blackColor]; cell.textLabel.font = [UIFont boldSystemFontOfSize:18]; cell.textLabel.adjustsFontSizeToFitWidth = YES; cell.detailTextLabel.textColor = [UIColor colorWithRed:100.0/255.0 green:100.0/255.0 blue:100.0/255.0 alpha:1]; cell.detailTextLabel.font = [UIFont italicSystemFontOfSize:16]; cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; NSString *detailText = [NSString stringWithFormat:@"%@ - %@",dateStr,idItems.GeoCode]; if (idItems.Image == NULL) { cell.imageView.image = [UIImage imageNamed:@"icon58x58.png"]; } else { //pass image to fix size 50 X 50 //UIImage *newImage = [self postProcessImage:idItems.Image]; cell.imageView.image = idItems.thumb;//newImage; cell.imageView.contentMode=UIViewContentModeScaleAspectFill; } cell.textLabel.text = idItems.TypeName; cell.detailTextLabel.text = detailText; return cell; } } - (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if(editingStyle == UITableViewCellEditingStyleDelete) { if ([idArray count] >=1) { [idTableView beginUpdates]; //Get the object to delete from the array. identifyObject = [appDelegate.idArray objectAtIndex:indexPath.row]; //Delete the object from the table. [self.idTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [appDelegate removeID:identifyObject]; if ([idArray count] == 0) { [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } [idTableView endUpdates]; } } } 

问题是tableview期望在视图上执行的操作与数据源匹配。 你在表格中有一条logging,并将其删除。 tableview期望数据源现在包含零个logging,但是由于你的“没有findlogging”的逻辑,它实际上返回一个3的值,因此一致性错误和你的崩溃。

这个错误似乎是这个部分:

 if ([idArray count] == 0) { [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } 

我假设这是为了在删除最后一行时向表中插入“找不到logging”行,但是因为“找不到logging”实际上跨越了三行,所以需要在这里插入三行,如下所示:

 if ([idArray count] == 0) { [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects: [NSIndexPath indexPathForRow:0 inSection:indexPath.section], [NSIndexPath indexPathForRow:1 inSection:indexPath.section], [NSIndexPath indexPathForRow:2 inSection:indexPath.section], nil] withRowAnimation:UITableViewRowAnimationFade]; } 

但是,为了您自己的理智,我可以提出一个不同的方法吗? 而不是试图保持你的表和数据源同步,而这些虚假的三行数据,只是出于显示的目的,为什么不插入一个UILabel到您的视图层次结构(无论是在前面或后面的tableview),说“没有findlogging“,并根据表是否有任何数据显示/隐藏它? 这样,您就可以精确地控制其位置和外观,而无需使用数据源逻辑。

处理删除行的一般规则是:

  1. 处理你的模型
  2. 处理行的animation

举个例子:

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { NSInteger row = [indexPath row]; [yourModel removeObjectAtIndex:row]; // you need to update your model [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } 

现在,在我看来,正确的代码可以是以下(我已经写了一些评论来指导你)。

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { //Get the object to delete from the array. identifyObject = [appDelegate.idArray objectAtIndex:indexPath.row]; [appDelegate removeID:identifyObject]; // update model first // now you can check model count and do what you want if ([appDelegate.idArray count] == 0) // I think you mean appDelegate.idArray { // do what you want // with [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else { [self.idTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } } 

希望能帮助到你。

我用同样的方法,我用一个单元格为“无行”警告。

对我来说,这工作:

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [favs removeObjectAtIndex:indexPath.section]; if ([favs count] == 0) { [tableView reloadRowsAtIndexPaths:[[NSArray alloc]initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade]; [tableView setEditing:NO animated:YES]; // Remove Edit bar button item self.navigationItem.rightBarButtonItem = nil; } else { // Animate the deletion from the table. [tableView deleteRowsAtIndexPaths:[[NSArray alloc]initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade]; } } 

}