奇怪的UIView-Encapsulated-Layout-Height错误

53

我正在制作一个测试应用程序,在故事板中的表格视图单元格中,我有imageViewwebView(用于显示HTML文本)。

我设置了约束,如imageView的顶部/左侧/右侧/高度=200,它们之间的间距为5,webView的左侧/右侧/底部,因此我想以编程方式计算我的webView的高度,然后更改单元格的高度以拉伸webView。但是我得到了以下结果:

Unable to simultaneously satisfy constraints.

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 & fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property

    translatesAutoresizingMaskIntoConstraints) 
    (
        "<NSLayoutConstraint:0x7fd6f3773f90 V:[UIImageView:0x7fd6f3773e90(200)]>",
        "<NSLayoutConstraint:0x7fd6f3774280 UIImageView:0x7fd6f3773e90.top == UITableViewCellContentView:0x7fd6f3462710.topMargin>",
        "<NSLayoutConstraint:0x7fd6f3774320 V:[UIImageView:0x7fd6f3773e90]-(5)-[UIWebView:0x7fd6f3462800]>",
        "<NSLayoutConstraint:0x7fd6f3774370 UITableViewCellContentView:0x7fd6f3462710.bottomMargin == UIWebView:0x7fd6f3462800.bottom>",
        "<NSLayoutConstraint:0x7fd6f375ee40 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fd6f3462710(205)]>"
    )

有什么建议吗?

可能是因为webview是一个scrollview,它被折叠到0高度,当单元格显示时,自动布局无法满足顶部和底部的约束条件。尝试在您的webview中放置一个固定的高度,看看是否仍然显示警告。 - Andrea
我在我的表视图中遇到了非常类似的问题。我无法正确调整单元格的大小,因为错误的“UIView-Encapsulated-Layout-Height”值优先级较高,并且由于单元格的内容视图(如我在IB故事板中制作的那样 - 使用约束)大于“UIView-Encapsulated-Layout-Height”。我甚至按照这个很棒的教程中的概念进行操作:http://www.raywenderlich.com/87975/dynamic-table-view-cell-height-ios-8-swift 但仍然无法使其正常工作!:( - Ethan G
6
我只想让“UIView-Encapsulated-Layout-Height”自动设置为单元格内容视图的高度(因为我在IB故事板中使用约束自己创建了内容视图)。我曾认为将tableView.rowHeight设置为UITableViewAutomaticDimension并将tableView.estimatedRowHeight设置为某个值就可以解决问题(就像Ray Wenderlich教程中所说),但是我做不到!! - Ethan G
我也遇到了同样的问题,伊桑。你找到解决方案了吗? - John Stewart
2
可能是[什么是NSLayoutConstraint“UIView-Encapsulated-Layout-Height”,我该如何强制它进行干净的重新计算]的重复问题(https://dev59.com/618f5IYBdhLWcg3wFfP_)。 - Ortwin Gentz
显示剩余3条评论
11个回答

92
我通常通过降低AutoLayout试图打破的约束的优先级来消除此警告。所以,如果它显示为:
Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fd7c2ecb520 V:[UIView:0x7fd7c2ecd0e0(300)]>

请将该任务的优先级降低到999

应该可以正常工作。

干杯。


7
可以,但底层的真正原因是什么呢? - Phineas Lue
谢谢!虽然这很傻,但我很高兴能够摆脱这个错误警告。 - flatpickles
2
它可以工作。结果显示警告 Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead. 你们遇到过这种情况吗? - hzwzw
这个解决方案对我在Xcode版本7.3.1(7D1014)中有效。我注意到,在我的情况下,IB中的UITableViewCell高度为131像素可以让IB自动布局引擎满意,但是contentView在IB中显示为130像素,这是不正确且无法更改的。我认为这是Xcode IB自动布局引擎和iOS运行时自动布局之间的一个bug。 - Neil
我已经将其应用于一个子视图,该子视图在动态高度的父视图上具有固定高度,并且它完美地工作。这有点合理。 - DragonCherry
显示剩余3条评论

17

如果您使用tableView.rowHeight = UITableViewAutomaticDimension,则应始终设置estimatedRowHeight。例如:

如果您使用tableView.rowHeight = UITableViewAutomaticDimension,则应始终设置estimatedRowHeight

tableView.estimatedRowHeight = 44

或者您应该实现:

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

否则您将始终收到警告UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView,并且内容将以错误的方式折叠


2
提醒其他读者注意,如果您正在使用标题和/或页脚,则还有.estimatedSectionHeaderHeight和.estimatedSectionFooterHeight属性。 - Trevis Thomas
1
FYI - 我发现在设置表视图的预估行高和实现函数方面存在差异。函数可以正常工作,但在我的情况下,设置器似乎无法正常工作。 - Mike

5

对于我来说,我使用估计的单元格高度。为了解决这个问题,我将标签底部到其邻居的约束优先级设置为999,并且它有效地解决了问题。


4

我目前见过两种情况会出现这种情况。一种情况在接受的答案中有记录,即tableView:heightForRow:实现必须返回与您的约束计算出的相同的值。

另一种情况是,如果您忘记在一个或多个自动布局视图上设置translatesAutoresizingMaskIntoConstraints = NO(或对于Swift为false),则会发生这种情况。在向以编程方式创建的视图添加约束之前,请关闭自动调整大小,如下所示:

view.translatesAutoresizingMaskIntoConstraints = false

否则,如果您的视图由自动调整大小掩码指定了固定的宽度或高度,则会创建一个约束来强制执行它。

3
以下代码对我不起作用。
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

不要将 translatesAutoresizingMaskIntoConstraints=false 添加到一堆视图中。

最后,在数据源回调函数 tableView:cellForRowAt 中删除 cell.updateConstraintsIfNeeded() 会使 Xcode 内容更加清晰。


1
是的,我曾经遇到过同样的问题。当单元格被重用时,请删除任何setNeedsLayout和layOutIfNeeded调用。 - Ankit J

3
我今天遇到了这个问题: - 使用Xcode 11 - 使用UITableViewAutomaticDimension - 使用estimatedRowHeight
解决该问题的因素之一是在故事板中将tableView的'Separator'属性设置为“None”。
此外,如果您的约束导致高度是分数(例如,如果您正在使用基于纵横比的乘数),那么它将与UIView-Encapsulated-Layout-Height产生冲突,后者始终被约束为整数值。 解决方案是略微降低高度约束的优先级。

很高兴能够解释为什么UIView-Encapsulated-Layout-Height会偏离0.5。 - trishcode
1
是的,tableView.separatorStyle = .none 解决了这个恼人的警告。 - Glenn Posadas

2

很抱歉我来晚了。 :)

如果约束条件是必需的,那么降低Autolayout试图打破的约束条件的优先级可能不是解决方案。

我最近遇到了这个问题,下面是我的布局:

  • OuterView <-- C1: 等于其父视图的宽度约束条件
    • StackView <-- C2: 等于OuterView的宽度约束条件
      • ChildView <-- C3: 固定宽度约束条件,常量=StackView.frame.size.width

当我减小C1的宽度时,就会出现问题,因为C3是一个固定宽度,它采用的是原始框架大小,所以减小C1会导致冲突,iOS会打破C1以修复问题。

通过将C3设置为采用StackView的widthAnchor而不是其框架大小,问题很快得到解决。

错误的约束条件

view.widthAnchor.constraint(equalToConstant: stackView.frame.size.width).isActive = true

正确的约束条件

view.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1.0).isActive = true

这样,每当C1发生变化时,所有子约束条件都会相应地做出反应。

结论:

  1. 我认为这个错误不是一些人所说的bug。
  2. 通过调整优先级来解决问题是可行的,但这是你想要的预期结果吗?
  3. 如果你决心在没有优先级的情况下解决它,请查看你的约束条件,特别是那些以编程方式设置的约束条件,以检查是否存在冲突。如果你正在处理视图的动态宽度或高度,例如单元格视图,请确保父视图的高度或宽度约束条件不会与这些动态变化发生冲突,并继续向上工作。

2
我今天遇到了一个问题,与屏幕上的一个集合视图无关。我正在使用自定义容器视图控制器,并且在容器视图本身布局之前,一些视图已经被布局了。
解决方法是通过在容器视图控制器上调用loadViewIfNeeded()来确保先布局容器视图。
这意味着如果原始问题中的0x7fd6f375ee40是来自视图控制器的视图,则需要检查是否在某些子视图布局之前加载了该视图层次结构。

1
这个错误发生在我使用 UIButton 时,试图通过创建一个与顶部和底部约束冲突的 UIView-Encapsulated-Layout-Height 来自动调整其高度。

我通过显式添加高度约束来解决它。


0

我试图实现一个简单的单元格,其中包含一行顶部标签和一个n行底部标签,当文本变长时会自动扩展,希望根据我的约束条件,单元格会自动扩展以适应内容。

有趣的是,对我来说,解决这个问题的方法是重写 - tableView:heightForRowAtIndexPath:tableView:estimatedHeightForRowAtIndexPath: 并返回我的估计行高和 UITableViewCellAutomaticDimension,而不是在 viewDidLoad: 中设置我的 tableView 的 rowHeightestimatedRowHeight


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