当我从UITableView
删除最后一条记录时遇到以下错误。
由于未捕获的异常而终止应用 'NSInternalInconsistencyException',原因:'无效更新:无效 第0节中的行数。包含在中的行数 更新后的现有部分(3)必须等于数量 在更新(1)之前,该部分中包含的行加或减 从该部分插入或删除的行数(插入1个, 删除1)加上或减去移入或移出的行数 该部分(0移入,0移出)。'
如果表数组为空,我的目标是显示“No Record found”。
这是我正在使用的代码。当我从表数组中删除最后一条记录时,应用程序崩溃了。如何重新加载表并显示“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];
}
}
}
答案 0 :(得分:14)
问题是tableview期望在视图上执行的操作与数据源匹配。表中有一条记录,您将其删除。 tableview期望数据源现在包含零记录,但由于你的“没有找到记录”逻辑,它实际上返回值3,因此出现一致性错误,以及你的崩溃。
这个错误似乎就是这个部分:
if ([idArray count] == 0) {
[self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
我认为这是为了在删除最后一行时将“找不到记录”行插入表中,但由于“找不到记录”实际上跨越了三行,所以你需要在这里插入三行,就像这样:
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的前面或后面),说“没有找到记录“并根据表格是否有任何数据显示/隐藏它?这样,您可以精确控制其位置和外观,而无需使用数据源逻辑。
答案 1 :(得分:10)
处理删除行的一般规则是:
例如:
- (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];
}
}
}
希望它有所帮助。
答案 2 :(得分:2)
我使用相同的方法,我使用单元格进行“无行”警告。
对我来说,这很有效:
- (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];
}
}
}