从UITableView中删除行的正确方法是什么?

时间:2013-06-07 16:46:40

标签: ios objective-c cocoa-touch uitableview

我有以下代码示例:

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

    if (editingStyle == UITableViewCellEditingStyleDelete) 
    {
        [namesArray removeObjectAtIndex:indexPath.row];

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];        
    }   
}

if ([nameSection count] == 0)
{
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
      [tableView beginUpdates];
      [indexKeys removeObjectAtIndex:section];
      [tableView deleteSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
      [tableView endUpdates];
}

注意顺序....在第一个例子中我首先从数组中删除对象,然后从tableview中删除该行。

在第二个例子中,我将从tableview中删除该行,然后从我的数组中删除该部分,然后从tableview中删除该部分。

这是正确的做事顺序吗?或者我应该首先从UI中删除它,然后是数组?

我问的原因是因为我收到一些报告这些崩溃的用户,我似乎无法重复:

  

NSInternalInconsistencyException - 无效更新:第1部分中的行数无效   更新(0)后必须包含在现有部分中的行   等于

之前该部分中包含的行数

使用此堆栈跟踪:

1: libobjc.A.dylib  objc_exception_throw 32
2: CoreFoundation  [NSException raise:format:] 0
3: Foundation  -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] 90
4: UIKit  -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] 6042
5: UIKit  -[UITableView _updateRowsAtIndexPaths:updateAction:withRowAnimation:] 254
6: UIKit  -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] 26
7: Movies  _mh_execute_header 253319
8: UIKit -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] 84
9: CoreFoundation  -[NSObject performSelector:withObject:withObject:] 52
10: UIKit  -[UIApplication sendAction:to:from:forEvent:] 62

2 个答案:

答案 0 :(得分:3)

您应该首先更新数据模型 ,否则表格视图会对正确的行数和部分数量感到困惑。

答案 1 :(得分:3)

表处于编辑模式后,表视图将询问数据源是否 每行都应该是可编辑的。如果tableView:canEditRowAtIndexPath:方法是 实现后,依次调用每一行。

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        return NO;
    }
    return YES;
}

确定是否可以编辑行后,表视图会询问代理 每行应使用哪种编辑样式:

-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleDelete;
}

当点击删除按钮时,tableView将tableView:commitEditingStyle:forRowAtIndexPath:消息发送到数据源。它需要三个参数:

1)对tableView本身的引用(如果数据源需要区分多个tableViews)。

2)刚刚被点击的控件的UITableViewCellEditingStyle - 在这种情况下,UITableViewCellEditingStyleDelete

3)定位相关行的indexPath对象。

当数据源收到commitEditingStyle:forRowAtIndexPath:消息时,它需要做两件事:

1)通过删除表中行所代表的对象来更新tableView的模型。请记住,表本身只是一个视图,除非我们实际从模型中删除对象,否则下次重新加载表时它将重新出现在表中。

2)将tableView:deleteRowsAtIndexPath:withRowAnimation:message发送到tableView,以便更新表格显示。在这种情况下,因为我们正在处理删除,它会将删除的单元格向左滑动,然后将其下方的单元格向上移动以缩小间隙。

-(void)tableView:(UITableView *)tableView 
  commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
   forRowAtIndexPath:(NSIndexPath *)indexPath {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            [self.tableData removeObjectAtIndex:indexPath.row];
            NSArray *indexPathArray = [NSArray arrayWithObject:indexPath];
            [tableView deleteRowsAtIndexPaths:indexPathArray
                             withRowAnimation:UITableViewRowAnimationAutomatic];
        }
    }

有一系列表格单元格插入和删除动画可供选择:

  1. UITableViewRowAnimationFade - 行淡入和淡出。
  2. UITableViewRowAnimationRight - 插入的行从右侧滑入;删除的行向右滑动。
  3. UITableViewRowAnimationLeft - 插入的行从左侧滑入;删除的行向左滑动。
  4. UITableViewRowAnimationTop - 插入的行从上面的行的底部向下滑动;删除的行向上滑动到上面行的底部。
  5. UITableViewRowAnimationBottom - 插入的行从下方单元格的顶部向上滑动;删除的行似乎被下面的行向上滑动覆盖。
  6. UITableViewRowAnimationNone - 只显示插入的行;删除的行只是消失了。
  7. UITableViewRowAnimationMiddle - 以手风琴式效果插入和删除单元格。
  8. UITableViewRowAnimationAutomatic - tableView会自动选择合适的动画样式(仅在iOS 5及更高版本中可用)。
  9. 关于如何使用表格的好书是here