UIStackView"无法同时满足约束"对"压扁"隐藏视图的影响

Ben*_*ild 90 uikit ios autolayout ios9 uistackview

当我的UIStackView"行"被压扁时,它们会AutoLayout发出警告.但是,它们显示正常,除了这些类型的记录之外别无其他错误:

无法同时满足约束.可能至少下列列表中的一个约束是您不想要的约束.试试这个:(1)看看每个约束并试着找出你不期望的东西; (2)找到添加了不需要的约束或约束的代码并修复它.(注意:如果您发现NSAutoresizingMaskLayoutConstraints自己不明白,请参阅该UIView物业的文件translatesAutoresizingMaskIntoConstraints)(

所以,我不知道如何解决这个问题,但它似乎并没有破坏任何东西,除了烦恼.

有谁知道如何解决它?有趣的是,布局约束经常使用"UISV隐藏"进行标记,这表明它可能应该忽略子视图的高度最小值或者此实例中的某些内容?

lia*_*ols 197

您遇到此问题是因为在将子视图从内部设置UIStackView为隐藏时,它将首先将其高度约束为零,以便将其设置为动画.

我收到以下错误:

2015-10-01 11:45:13.732 <redacted>[64455:6368084] 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:0x7f7f5be18c80 V:[UISegmentedControl:0x7f7f5bec4180]-(8)-|   (Names: '|':UIView:0x7f7f5be69d30 )>",
    "<NSLayoutConstraint:0x7f7f5be508d0 V:|-(8)-[UISegmentedControl:0x7f7f5bec4180]   (Names: '|':UIView:0x7f7f5be69d30 )>",
    "<NSLayoutConstraint:0x7f7f5bdfbda0 'UISV-hiding' V:[UIView:0x7f7f5be69d30(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7f7f5be18c80 V:[UISegmentedControl:0x7f7f5bec4180]-(8)-|   (Names: '|':UIView:0x7f7f5be69d30 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Run Code Online (Sandbox Code Playgroud)

我试图做的是UIView在我的内部放置一个每边8分UIStackViewUISegmentedControl插图.

当我将其设置为隐藏时,它会尝试将容器视图约束到零高度,但因为我从上到下有一组约束,所以存在冲突.

为了解决这个问题,我将我的8pt top从底部约束优先级从1000更改为999,以便在UISV-hiding需要时可以优先考虑约束.

  • 改变优先事项对我也有用.此外,删除从未使用的大小类中意外复制的任何多余(变暗)约束.重要提示:要更轻松地调试这些问题,请在每个约束上设置IDENTIFER字符串.然后你可以在调试消息中看到哪个Constraint是顽皮的. (4认同)
  • 在我的情况下,我只需降低高度的优先级,它的工作原理. (3认同)

Sen*_*ful 48

我遇到了一个不容易解决的类似问题.就我而言,我在堆栈视图中嵌入了堆栈视图.内部UIStackView有两个标签,并指定了非零间距.

当您调用addArrangedSubview()时,它将自动创建类似于以下内容的约束:

V:|[innerStackView]|              | = outerStackView

  V:|[label1]-(2)-[label2]|       | = innerStackView
Run Code Online (Sandbox Code Playgroud)

现在,当您尝试隐藏innerStackView时,会出现模糊约束警告.

要理解为什么,让我们首先看看为什么当等于时不会发生这种情况.当你打电话,@liamnichols是正确的......在会奇迹般地截获此调用,并创建一个高度UISV隐藏优先约束1000(必需).据推测,这是为了在块中调用隐藏代码时允许堆栈视图中的元素被动画化.不幸的是,似乎没有办法阻止添加这种约束.然而,由于发生以下情况,您将无法获得"无法同时满足约束"(USSC)警告:innerStackView.spacing0innerStackView.hidden = trueouterStackView0UIView.animationWithDuration()

  1. label1的高度设置为0
  2. 两个标签之间的间距已经定义为0
  3. label2的高度设置为0
  4. innerStackView的高度设置为0

很明显,可以满足这4个约束条件.堆栈视图只是将所有内容扫描成0高度的像素.

现在回到错误的例子,如果我们设置spacing2,我们现在有这些约束:

  1. label1的高度设置为0
  2. 堆栈视图自动创建两个标签之间的间距为2像素高,1000优先级.
  3. label2的高度设置为0
  4. innerStackView的高度设置为0

堆栈视图不能都是0像素高并且其内容高度为2像素.不能满足约束.

注意:您可以通过一个更简单的示例来查看此行为.只需将UIView添加到堆栈视图作为排列的子视图.然后在该UIView上设置一个高度约束,优先级为1000.现在尝试在上面调用hide.

注意:无论出于何种原因,这只发生在我的堆栈视图是UICollectionViewCell或UITableViewCell的子视图时.但是,您仍然可以通过innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)在隐藏内部堆栈视图后调用下一个运行循环来在单元格外重现此行为.

注意:即使您尝试在UIView.performWithoutAnimations中执行代码,堆栈视图仍会添加0高度约束,这将导致USSC警告.


此问题至少有3种解决方案:

  1. 在隐藏堆栈视图中的任何元素之前,检查它是否是堆栈视图,如果是,则将spacing其更改为0.这很烦人,因为每当再次显示内容时,您需要反转过程(并记住原始间距).
  2. 不要将元素隐藏在堆栈视图中,而是调用removeFromSuperview.这更令人讨厌,因为当你颠倒过程时,你需要记住在哪里插入被删除的项目.你可以通过调用removeArrangedSubview然后隐藏来优化,但是仍然需要完成大量的簿记.
  3. spacing在UIView中包装嵌套的堆栈视图(非零).将至少一个约束指定为非必需优先级(999或更低).这是最好的解决方案,因为您不必进行任何簿记.在我的示例中,我在堆栈视图和包装器视图之间创建了1000的顶部,前导和尾随约束,然后从堆栈视图的底部到包装器视图创建了一个999约束.这样,当外部堆栈视图创建零高度约束时,999约束将被破坏,并且您不会看到USSC警告.(注意:这类似于解决方案应该将UICollectionViewCell子类的contentView.translatesAutoResizingMaskToConstraints设置为false)

总之,您获得此行为的原因是:

  1. 将托管子视图添加到堆栈视图时,Apple会自动为您创建1000个优先级约束.
  2. 当您隐藏堆栈视图的子视图时,Apple会自动为您创建0高度约束.

如果Apple(1)允许您指定约束的优先级(尤其是间隔),或者(2)允许您选择退出自动UISV隐藏约束,则可以轻松解决此问题.

  • 感谢超级彻底和有用的解释.然而,这绝对看起来像苹果方面的堆栈视图的错误.基本上他们的"隐藏"功能与他们的"间距"功能不兼容.他们的任何想法都解决了这个问题,或者添加了一些功能以防止黑客攻击额外的包含视图?(同样,潜在解决方案的大量细分,并同意#3的优雅) (6认同)

小智 6

大多数情况下,可以通过降低约束优先级来解决此错误,以消除冲突.