什么是_UITemporaryLayoutWidth,为什么它会破坏我的约束?

问题描述 投票:37回答:9

我有一个包含Autolayout和Size Classes的故事板。相当复杂的布局,不幸的是我无法确定如何在新项目中重现问题。 但是有问题的视图被固定在屏幕的左边缘和右边缘,其约束具有750优先级(即|-(0@750)-[myView]-(0@750)-|,另外它具有大于或等于约束的优先级为1000(即|-(>=0)-[myView]-(>=0)-|)。限制iPad上的宽度,因此有一个width <= 600 @1000的宽度约束,以及容器约束中的中心水平。最重要的是,视图的宽高比约束为3:1。正如我所说,相当复杂。

Interface Builder不会显示约束的任何问题。 Xcode布局预览为所有设备呈现正确。

当我运行应用程序iOS时告诉我它有相互冲突的约束。

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 and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fd72853ff80 DMXKit.DipSwitchAssembly:0x7fd72990d0e0.width == 3*DMXKit.DipSwitchAssembly:0x7fd72990d0e0.height>",
    "<NSLayoutConstraint:0x7fd728574e50 '_UITemporaryLayoutWidth' H:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(400)]>",
    "<NSLayoutConstraint:0x7fd72856e9c0 V:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(133)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7ffb19798000 DMXKit.DipSwitchAssembly:0x7ffb1979a000.width == 3*DMXKit.DipSwitchAssembly:0x7ffb1979a000.height>

这重复了几次,具有完全相同(即相同的指针)约束。这也很奇怪,看起来约束并没有真正破坏。运行时,该应用程序看起来100%正确。当我在Xcode视图调试器中查看应用程序时,地址为0x7ffb19798000的约束仍然存在,因此它永远不会被破坏。

_UITemporaryLayoutWidth constaint来自哪里?显然我没有添加它。谷歌没有吐出任何有关_UITemporaryLayoutWidth的有用信息。有没有人遇到这样的问题?

ios autolayout nslayoutconstraint
9个回答
52
投票

因此,我不确定这是否可以帮助您解决问题,因为它听起来像是在IB中构建您的布局,但这是我刚遇到的一个问题,可能有助于谷歌搜索“_UITemporaryLayoutWidth”的其他人。

我的情况是我在init期间添加了自动布局约束,并且在将视图添加到视图层次结构(修改按钮边缘插入触发器布局)之前意外触发了“layoutIfNeeded”。看起来系统添加了这些临时约束并且(我假设?)在将视图添加到层​​次结构后将其删除。临时约束设置0维度(在我的情况下),如果您在布局中设置特定约束常量值(例如,您希望这些按钮之间有16个像素,但该维度中有0个空格......),则可能会失败。

更新:调查了一下,发现临时约束似乎对应于用于初始化父视图的框架。在我的例子中,我使用的帧大小为0x0,因此临时约束相对于0x0大小进行了评估,因此失败了。验证如果我使用5x5帧初始化,那么我会看到与_UITemporaryLayoutWidth(5)约束相同的错误。我注意到的另一件事是在布局评估期间似乎添加和删除了约束 - 如果我在触发布局之前断开并分析约束,那么我没有看到临时约束。我也没有看到错误后的约束,所以我怀疑他们合成了临时约束,添加它们,解决然后删除它们。

更新2:好的,也许这是TMI,但这可能对某人有用。我目前的想法是,这些临时约束可以看出系统如何在单个视图层次结构中处理混合帧操作和自动布局。在我的情况下,我的视图没有父级,没有约束来定义它的大小,但它确实有一个零帧,这意味着系统假设它是解决布局时应该使用的大小。我的想法是系统为视图合成这些临时约束,这些视图明确地设置了框架,以便在遍历层次结构时解决系统的其余部分。

更新3:所以,我再次遇到这个问题,并希望分享更多的信息。我的情况是我试图基本上使用systemLayoutSizeFittingSize:方法测量没有父级的视图。简而言之,我必须在测量之前在视图上调用layoutIfNeeded - 这是我遇到临时约束冲突的地方,因为视图没有超视图。临时约束常量(维度)确实对应于没有超视图的视图上设置的任何帧 - 我认为这是有道理的(但是,在将要与AutoLayout一起使用的视图上设置框架似乎很奇怪.. 。)我能够解决临时约束问题 - 如果视图没有超视图,那么将其添加到临时超视图中;测量;从临时superview中删除它。希望这很有用。


14
投票

如上所述,临时约束似乎是在没有父视图的视图上设置的。我发现确保translatesAutoresizingMaskIntoConstraints是顶级视图上的false删除了临时约束。如:

topView.translatesAutoresizingMaskIntoConstraints = false

8
投票

我的情况,问题如下:

我创造了一个UIButton。 我设置了它的宽度和高度限制。 我将按钮添加到其超级视图中。 我将其主要和顶部布局约束设置为superview。

这造成了错误“Unable to simultaneously satisfy constraints”,其中一个冲突的约束是_UITemporaryLayoutHeight

当我在设置宽度和高度约束之前将按钮添加到其超视图时,错误消失了。


2
投票

只是对上述注释的快速补充,对我有用的简单解决方案是更改创建约束的顺序。我以编程方式在视图和超级视图上创建约束 - 但我在超级视图之前做了视图。所以我交换它以便超级视图约束首先出现,然后子视图添加了约束,这意味着不再调用_UITemporaryLayoutWidth,因此约束问题消失了。


2
投票

在我的情况下,我在这种情况下只有这个UITemporaryLayoutWidth冲突1我用[UIView new]创建一个视图,我没有将它添加到任何superview 2然后我创建一个宽度约束到这个视图只是被创建3调用layoutIfNeeded到这个观点立即发生,冲突就发生了

所以消除这个错误的方法很简单:在添加到某个superview之前,不要将layoutIfNeeded调用它


1
投票

我的UITemporaryLayoutWidth问题是我以编程方式创建按钮,tempWidth约束约为我的宽度约束0.1。 (虽然令人讨厌,这只发生在我创建按钮的多种方式之一中创建按钮时)

问题是我使用.adjustsFontSizeToFitWidth = true作为按钮标题。

我评论说这条线并且它消失了。


1
投票

今天在这个问题上花了几个小时。我在初始化元素之后立即设置了我的UIButton imageView的contentMode,这似乎在我在我的顶级类(其中包括约束高度/宽度)中设置约束之前强制布局。


1
投票

当我使用视图的layout-margin锚点添加约束时,我遇到了这个问题。当我将布局边距锚点的约束更改为视图的顶部,底部,前导,尾随锚点时,错误消失了。

我用.zero rect创建了我的超级视图。

但由于我需要加入视图的边距,我不得不做一点点破解。我改变了约束的优先级。

我得到临时宽度和临时高度错误。所以我沿着水平轴降低了一个约束的优先级,沿着垂直轴降低了一个约束(在这种情况下是顶部和尾部约束):

    let topConstraint = stackView.topAnchor.constraint(equalTo: margins.topAnchor)
    topConstraint.priority = .init(rawValue: 999.0)
    topConstraint.isActive = true

    let trailingConstraint = stackView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
    trailingConstraint.priority = .init(rawValue: 999.0)
    trailingConstraint.isActive = true

原因是因为我使用.zero rect初始化我的视图iOS会自动添加临时宽度和高度限制。此时如果我们添加具有高优先级的其他约束,它将破坏生成错误日志。

降低优先级可以修复破坏约束,当删除临时约束时,我们的视图将得到正确的形状。


0
投票

问题的根源是3:1的宽高比。如果我把它改成其他的东西,我现在使用4:1.4,它的工作原理。我不知道为什么,但它确实有效。

我不太了解自动布局的内部结构,但我认为,问题在于布局引擎如何实现约束。大小类可能是添加临时宽度约束的原因。

不可满足的约束似乎不是一个真正的问题,因为它看起来只是暂时不可满足。每次创建视图时,只会显示几行日志。

© www.soinside.com 2019 - 2024. All rights reserved.