在调用 reloadData 之前,自动布局会错误地调整 UITableViewCells

Posted

技术标签:

【中文标题】在调用 reloadData 之前,自动布局会错误地调整 UITableViewCells【英文标题】:Autolayout sizes UITableViewCells incorrectly until reloadData is called 【发布时间】:2014-09-21 20:04:10 【问题描述】:

我有一个表格视图单元格,其视图是从笔尖加载的,并且其子视图使用 AutoLayout 进行约束。我正在使用 ios 8 的自调整单元格功能。在第一次显示时,单元格如下所示:

绿色视图与蓝色和灰色视图之间的边距比我预期的要大。如果我向下滚动视图以便创建更多单元格,或者如果我在 tableview 上调用 reloadData,那么我会得到正确的结果:

在第二次布局通过之前,好像单元格子视图的大小不正确。我怎样才能解决这个问题?我看过一些帖子建议在layoutSubviews 中设置setPreferredMaxLayoutWidth,如下所示:

-(void)layoutSubviews

    [super layoutSubviews];
    [self.redLabel setPreferredMaxLayoutWidth:[self.titleLabel bounds].size.width];
    [self.greenLabel setPreferredMaxLayoutWidth:[self.extendedLabel bounds].size.width];
    [self.blueLabel setPreferredMaxLayoutWidth:[self.dateLabel bounds].size.width];
    [self.grayLabel setPreferredMaxLayoutWidth:[self.tagsLabel bounds].size.width];
    [super layoutSubviews];

...不过好像没有效果。

我的约束似乎没有任何歧义,但由于它们是在 .nib 中设置的,我不知道如何在此处发布它们。


编辑 1:

所以我将蓝色/灰色视图的顶部空间设置为 >= 绿色视图的底部,+3。这实际上是我得到的,因为空间更大。

但是,如果我将关系设置为 ==,则会出现不同的视觉错误,其中红色标签的大小与其包含的文本量不正确:


编辑 2:

不确定我是否应该开始一个新问题,但这是同一个问题。

仍然存在与编辑 1 中一样的布局问题。除了视觉问题之外,当我的表格视图中的单个单元格发生变化时,它会产生可怕的影响。整个列表将出现折叠并重新加载。此外,我记录了以下自动布局错误:

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x797c5bc0 UITableViewCellContentView:0x7970adc0.(null) == UILabel:0x79707cf0.trailing + 6>",
    "<NSLayoutConstraint:0x7977b560 UILabel:0x79707cf0.leading == UITableViewCellContentView:0x7970adc0.(null) + 6>",
    "<NSLayoutConstraint:0x7970a700 UITableViewCellContentView:0x7970adc0.width ==>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x797c5bc0 UITableViewCellContentView:0x7970adc0.(null) == UILabel:0x79707cf0.trailing + 6>

UILabel 所指的是较长的绿色标签。似乎它无法将前导约束和尾随约束与单元格具有的任何宽度相协调,就好像单元格总体上小于 12 点一样。但是,注销宽度似乎总是导致 320。

【问题讨论】:

你找到解决办法了吗? 【参考方案1】:

补充一点,因为大多数人都提出了对我不起作用的建议,所以这是我修复它的方法(适用于 iOS 8)。我将 XIB 用于单元格,但这应该是通用的。

首先,UILabel 上有一个错误,其中没有调用“-(void)layoutSubviews”,因此您无法真正让 iOS 7.0 解决方案适用于 iOS 8。因此,我使用自动调整单元格大小iOS 8。

但是,上面描述的错误正在发生。我必须重新加载表格视图才能使单元格正确。如果您查看那里的教程和示例,那里有很多工作正常,而其他人则抱怨存在错误。我一直在寻找错误示例和正确示例之间的共同点,错误是:size-classes.

不要使用“compact-width”和“any-height”,而是使用“any-any”。使用“any-any”解决了所有问题,一切都按预期工作。听起来很荒谬,但试试吧!

【讨论】:

我在聚会上迟到了,但对单元格和尺寸等级感到头疼。但是,如果我需要不同的 iphone 和 ipad 布局怎么办?你能做到吗? 不,抱歉,我只需要在 iPhone 上试试这个 我在viewWillAppear 中调用tableView.layoutIfNeeded。您也可以先调用tableView.setNeedsLayout 来强制重绘。 iOS 9 和 iPhone。【参考方案2】:

难道不是布局的问题,而是单元格高度计算的问题?我会仔细检查您的估计HeightForRowAtIndexPath 或 heightForRowAtIndexPath。

【讨论】:

好主意,但我的 rowHeight 是 UITableViewAutomaticDimension,estimatedRowHeight 是 88.0,这似乎不会影响视图大小。 (我没有实现代表)。【参考方案3】:

使用 Xcode 6 的视图调试工具查看您的自动布局约束是否存在问题。如果您发现情况并非如此,那么@niklassaers 可能是对的。

【讨论】:

所以我将蓝色/灰色视图的顶部空间设置为 >= 绿色视图的底部,+3。这可能是导致问题的原因。但是,如果我将关系设置为 ==,则会出现不同的视觉错误(请参阅问题编辑)。

以上是关于在调用 reloadData 之前,自动布局会错误地调整 UITableViewCells的主要内容,如果未能解决你的问题,请参考以下文章

在所有子视图自动布局之前调用 viewWillTransitionToSize

自定义 CollectionView 布局重新加载数据不起作用

UICollectionView `reloadData` 导致 UILabel 行消失

集合单元在每个 reloadData() 调用 Swift 5 时删除项目

在视图出现在屏幕上之前进行转换时,自动布局错误地定位子视图

UITableView 的 tableViewHeader 和 tableViewCells 重叠,直到调用 reloadData