setNeedsLayout仅在显示之后重新布局单元格

cov*_*ack 7 uitableview ios autolayout

我有一个带有单元格的表格视图,有时会有一个可选的UI元素,有时它必须被删除.根据元素,调整标签大小.

当细胞初始化时,它比以后更窄.当我将数据设置到标签中时,将调用此代码cellForRowAtIndexPath:

if (someFlag) {
    // This causes layout to be invalidated
    [flagIcon removeFromSuperview];
    [cell setNeedsLayout];
}
Run Code Online (Sandbox Code Playgroud)

之后,单元格返回到表视图,并显示它.但是,该点的文本标签已调整其宽度,但不调整高度.大约一秒后调整高度,并且当已经显示所有单元格时,可以清楚地看到加加速度.

重要提示,这只是在初始创建前几个单元格时.一旦它们被重复使用,一切都很好,因为删除了可选视图,并且标签已经在之前的用法中正确调整了大小.

为什么在细胞setNeedsLayout显示之前没有完全重新铺设细胞?UIKit不应该在显示前检查无效布局吗?

如果我做

if (someFlag) {
    [flagIcon removeFromSuperview];
    [cell layoutIfNeeded];
}
Run Code Online (Sandbox Code Playgroud)

一切都得到调整,但这似乎是一种不正确的编写代码的方式,我觉得我错过了其他的东西.


关于如何创建单元格的更多代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ProfileCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    [cell setData:model.items[indexPath.row] forMyself:YES];
    return cell;
}

// And in ProfileCell:
- (void)setData:(Entity *)data forMyself:(BOOL)forMe
{
    self.entity = data;

    [self.problematicLabel setText:data.attributedBody];
    // Set data in other subviews as well

    if (forMe) {
        // This causes layouts to be invalidated, and problematicLabel should resize
        [self.reportButton removeFromSuperview];
        [self layoutIfNeeded];
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,如果它很重要,在storyboard单元格看起来像这样,可选约束接管一旦标志图标被删除: 故事板中的约束

bil*_*tum 4

我同意打电话layoutIfNeeded似乎是错误的,尽管它适用于您的情况。但我怀疑你错过了什么。尽管我没有对此方式进行任何研究,但根据我的经验,在进行动态布局的表格单元格中使用自动布局有点问题。也就是说,在运行时向单元格中删除或添加子视图时,我会看到不稳定的布局。

如果您正在寻找替代策略(使用自动布局),您可以子类化UITableViewCell并覆盖layoutSubviews. 自定义表格单元格可以在其公共 API 中公开一个标志,该标志可以在tableView:cellForRowAtIndexPath:. 单元格的layoutSubviews方法将使用该标志来确定它是否应包含可选的 UI 元素。不过,我不保证这会消除问题。

第二种策略是设计两种独立的单元类型,并tableView:cellForRowAtIndexPath:根据需要在两种单元之间进行交换。