调用deleteRowsAtIndexPaths时,具有自定义单元格的UITableView变得不稳定

时间:2016-12-27 09:47:39

标签: ios objective-c uitableview nslayoutconstraint ios-autolayout

我有一个带有自定义单元格的UITableView。表包含1个部分和一些行。我有一些行说30,我想在didSelectRowAtIndexPath期间删除行。

当我删除tableview底部附近可用的行(例如第28行)时,第28行之前的行会改变它们的位置,并且由于deleteRowsAtIndexPaths而导致动画不稳定。有关详细信息,请参阅附带的GIF。

Cells constructed with frame deletion animation

Auto Resizing cells Deletion animation

  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  {

       return 1;
  }
  -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  {
    return UITableViewAutomaticDimension;
  }

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return noOfRows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    [cell setCellText:[NSString stringWithFormat:@"Section = %li Row = %li", indexPath.section,indexPath.row]];

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    noOfRows--;
    [tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
}

这种不稳定的动画只发生在自我调整大小的单元格中,而不是由用框架构造的单元格发生。 任何帮助将不胜感激。

编辑1:问题是内容偏移和内容大小。让我们说表格视图中的每个单元格的高度为50.因此,对于20个单元格,内容大小约为1000.让我们将设备高度视为200,将宽度视为100.因此内容大小将为100,1000。当我滚动到tableview底部时,内容偏移变为0,800。当我现在删除一行时,内容大小将更新为100,950,内容偏移现在会尝试根据内容大小的变化调整为新值。所以这会导致混乱。

2 个答案:

答案 0 :(得分:4)

生涩的动画是由于您的细胞估计的不正确高度造成的。因此,您需要在表视图控制器中实现estimatedRowHeight并返回保存的高度。您可以将willDisplayCell tableView委托方法中先前加载的单元格高度保存为数组中的cell.frame.size.height

var estimatedHeights : [CGFloat] = []

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
        if estimatedHeights.count > indexPath.row
        {
            return estimatedHeights[indexPath.row]
        }

        return 40

}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{


        if estimatedHeights.count <= indexPath.row
        {
            estimatedHeights.append(cell.frame.height)

        }
        else
        {
            estimatedHeights[indexPath.row] = cell.frame.height

        }

}

同时将您的删除代码放在[tableView beginUpdates];[tableView endUpdates];

答案 1 :(得分:1)

像这样更新您的方法并尝试:

<强> cellForRowAtIndexPath:

[cell setNeedsUpdateConstraints];
[cell layoutIfNeeded];

didSelectRowAtIndexPath:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    noOfRows--;
[tableView beginUpdates];
    [tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}