在UITableView中使用插入行

32

我希望我的UITableView的行为像联系人编辑器中的表格一样,即用户应该点击“编辑”按钮,然后“添加新类别”行应该出现在每个部分的底部。

我正在使用以下代码来实现此功能,但问题是没有像联系人一样平滑的过渡。相反,新行会突然出现。如何获得动画效果?

还有,如何响应对“添加新类别”行的点击?在我的当前实现中,该行无法点击。

当用户开始编辑时,我需要重新加载数据吗?如果不这样做,则插入行永远不会被绘制。

谢谢。

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [self.tableView setEditing:editing animated:animated];
    [tableView reloadData];
}

- (NSInteger)tableView:(UITableView *)_tableView numberOfRowsInSection:(NSInteger)section {
    // ...
    if( self.tableView.editing ) 
        return 1 + rowCount;
}

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // .....
    NSArray* items = ...;
    if( indexPath.row >= [items count] ) {
        cell.textLabel.text = @"add new category";
    }
    // ...

    return cell;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSArray* items = ...;

    if( indexPath.row == [items count] )
        return UITableViewCellEditingStyleInsert;

    return UITableViewCellEditingStyleDelete;
}

2
这非常有帮助(还有下面的答案)。只有一个小矛盾 - 在tableView:cellForRowAtIndexPath:中与行数比较使用了> =,而在tableView:editingStyleForRowAtIndexPath:中使用了==。虽然不是很重要,但它们之间应该保持一致。 > =将覆盖任何意外的双倍添加插入行,而==将通过为可能导致该情况的任何代码错误引发异常来提供帮助。 - David Ravetti
3个回答

36

我漏掉了一件事。在setEditing:中,我不应该调用reloadData,而应该执行以下操作:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController

    NSMutableArray* paths = [[NSMutableArray alloc] init];

    // fill paths of insertion rows here

    if( editing )
        [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom];
    else
        [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom];

    [paths release];
}

3
谢谢Bill,这对我非常有用。我花了几个小时在类似的代码中摸索,但无法完全弄清楚。这次帮助非常大。 - hkatz
commitEditingStyle: forRowAtIndexPath 这个方法怎么处理呢?苹果文档说当表格视图第一次进入编辑模式时会调用 setEditing 方法... 那么此时如何知道要插入/删除哪些行呢? - shim
我不明白你的问题。 - Bill
我发现当滑动单行时,会调用-setEditing:animated:方法。在这种情况下,您不想插入带有“+”按钮的行。(也许这就是shim所指的?) - bio

5

响应单击行可在didSelectRowAtIndexPath方法中完成,即对于indexPath.row == [items count]的情况。有关动画方面,我建议通过此处insertRowsAtIndexPaths:withRowAnimation:方法进行查看。有一篇关于如何使用它的帖子请参见此处


0
突出解决方案的一个不良副作用是,即使用户只滑动了一行(前提是启用了滑动),也会插入“添加”行。以下代码解决了这个问题:
// Assuming swipeMode is a BOOL property in the class extension.

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Invoked only when swiping, not when pressing the Edit button.
    self.swipeMode = YES;
}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.swipeMode = NO;
}

你的代码需要进行一个小改动:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController

    if (!self.swipeMode) {

        NSMutableArray* paths = [[NSMutableArray alloc] init];

        // fill paths of insertion rows here

        if( editing )
            [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom];
        else
            [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom];
        [paths release];
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接