【问题标题】:Weird UITableView insert/delete row animation奇怪的 UITableView 插入/删除行动画
【发布时间】:2014-04-11 19:57:11
【问题描述】:

在带有动画 (UITableViewRowAnimationTop) 的 UITableView 中插入/删除 UITableViewCell 时,我看到了一种奇怪的效果。

当要插入的单元格比上面的单元格大得多时,就会出现动画故障。

This video 显示模拟器中的故障,黄色单元格在它应该从顶部滑动时突然出现。

Here 是视频中的 Xcode 项目。

下面是单元格插入/动画代码。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2 + self.thirdCellVisible;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    if (indexPath.row == 1)
    {
        if (self.thirdCellVisible)
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];
        }
        else
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];
        }
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == self.thirdCellIndexPath.row)
    {
        return 100.0f;
    }

    return 44.0f;
}

【问题讨论】:

  • 该项目的链接显然已被删除。你能把它放回去吗?
  • @Sheamus 您可以轻松地在代码中重新生成。尝试在 UITableView 中插入一个具有动态行的单元格。
  • @Nicholas :您必须分别在调用插入/删除方法之前和之后调用 [tableView beginUpdates][tableView endUpdates]
  • @kidsid49:我的答案如下。

标签: ios uitableview animation


【解决方案1】:

你必须打电话

[tableView beginUpdates] 

[tableView endUpdates] 

在调用插入/删除方法之前和之后如下:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2 + self.thirdCellVisible;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    if (indexPath.row == 1)
    {
        if (self.thirdCellVisible)
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [self.tableView beginUpdates];

            [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];

            [self.tableView endUpdates];

        }
        else
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [self.tableView beginUpdates];

            [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];

            [self.tableView endUpdates];

        }
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == self.thirdCellIndexPath.row)
    {
        return 100.0f;
    }

    return 44.0f;
}

【讨论】:

  • 为什么?没有批量插入或删除。
【解决方案2】:

根据Apple here

动画批量插入、删除和重新加载行和 部分,在动画块中调用相应的方法 由对 beginUpdates 和 endUpdates 的连续调用定义。如果你 不要在 this 中调用插入、删除和重新加载方法 块、行和部分索引可能无效。调用 beginUpdates 并且 endUpdates 可以嵌套;所有索引都被视为有 只有外部更新块。

在一个块结束时——也就是说,在 endUpdates 返回之后—— 表视图像往常一样查询其数据源和委托以获取行和 部分数据。因此支持表视图的集合对象 应该更新以反映新的或删除的行或部分。

您必须分别在调用插入/删除方法之前和之后调用[tableView beginUpdates][tableView endUpdates]

Apple 在上述链接中提供了一个示例。

注意:如果您的数组和表格视图项不同步,如果没有开始/结束调用,则会引发异常。

建议:先试试withRowAnimation:UITableViewRowAnimationAutomatic

【讨论】:

  • 但是 OP 没有进行批量插入、删除或重新加载。他们只进行一次插入或删除。所以不需要使用beginUpdatesendUpdates
  • 方法 [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] 接受一个索引路径数组,所以这是一个浴缸插入。
  • 不,如果您多次调用 insertRows/deleteRows/reloadRows,这是一个批处理。
  • 该讨论不适用于此处。 OP 仅插入或删除单行。一行不是一批。
【解决方案3】:

这是我的工作代码的视频链接:https://dl.dropboxusercontent.com/u/30316681/480.mov

下面是我的工作代码:

@interface ViewController ()

@property (nonatomic, readwrite) BOOL thirdCellVisible;
@property (nonatomic, strong) NSIndexPath *thirdCellIndexPath;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.thirdCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:0];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2 + self.thirdCellVisible;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == self.thirdCellIndexPath.row)
    {
        return 100.0f;
    }

    return 44.0f;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    if (indexPath.row == 1)
    {
        if (self.thirdCellVisible)
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                         withRowAnimation:UITableViewRowAnimationTop];
        }
        else
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                         withRowAnimation:UITableViewRowAnimationTop];
        }
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellId = @"id";

    UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:cellId];

    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
    }

    NSString *cellTitle = [NSString stringWithFormat:@"Cell %ld", (long)indexPath.row];

    cell.textLabel.text = cellTitle;

    if(indexPath.row == 2)
        cell.backgroundColor = [UIColor yellowColor];

    else
        cell.backgroundColor = [UIColor clearColor];

    return cell;
}

@end

【讨论】:

    【解决方案4】:

    如下使用[tableView beginUpdates][tableView endUpdates]

      - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    
    {
        [tableView deselectRowAtIndexPath:indexPath animated:NO];
    
        if (indexPath.row == 1)
        {
            if (self.thirdCellVisible)
            {
                self.thirdCellVisible = !self.thirdCellVisible;
    
                [self.tableView beginUpdates];
                [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                                 withRowAnimation:UITableViewRowAnimationTop];
                 [self.tableView endUpdates];
    
            }
            else
            {
                self.thirdCellVisible = !self.thirdCellVisible;
    
                [self.tableView beginUpdates];
                [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                                 withRowAnimation:UITableViewRowAnimationTop];
                 [self.tableView endUpdates];
    
            }
        }
    }
    

    【讨论】:

    • 为什么?没有批量插入或删除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多