自动布局:什么创build了名为UIView-Encapsulated-Layout-Width&Height的约束?

在Interface Builder中,我的布局约束没有问题,但在运行时发生exception,这要归功于框架的某些部分应用固定的高度和宽度约束,我真的不想要。 他们为什么在那里,如何把他们closures?

它们是日志列表中显示的最后两个约束:

2014-04-26 09:02:58.687 BBCNews[32058:60b] 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:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>", "<NSLayoutConstraint:0xbf47190 UIView:0xbf4a3c0.leading == BNMyNewsCell_landscape:0xbf48b10.leading>", "<NSLayoutConstraint:0xbf47160 UIView:0xbf4a3c0.trailing == BNMyNewsCell_landscape:0xbf48b10.trailing>", "<NSLayoutConstraint:0xbf47130 BNMyNewsCell_landscape:0xbf48b10.bottom == UIView:0xbf4a3c0.bottom>", "<NSLayoutConstraint:0xbf47100 UIView:0xbf4a3c0.top == BNMyNewsCell_landscape:0xbf48b10.top>", "<NSLayoutConstraint:0xd4c3c40 'UIView-Encapsulated-Layout-Width' H:[BNMyNewsCell_landscape:0xbf48b10(304)]>", "<NSLayoutConstraint:0xd4c38a0 'UIView-Encapsulated-Layout-Height' V:[BNMyNewsCell_landscape:0xbf48b10(290)]>" } Will attempt to recover by breaking constraint <NSLayoutConstraint:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width> 

基于大量的观察,我相信(但不能肯定),名为UIView-Encapsulated-Layout-WidthUIView-Encapsulated-Layout-HeightUICollectionView是由UICollectionView和朋友创build的,并存在强制执行由sizeForItemAtIndexPath委托方法。 我想这是为了确保由UICollectionViewCell设置的cellForItemAtIndexPath结束了它被告知的大小。

这里回答我最初的问题。 第二个问题是为什么这些约束是不可满足的? 单元格的内在高度应该与UIView-Encapsulated-Layout-Height 。 再次,我不知道确定,但我怀疑这是一个舍入误差(即固有高度达到200.1像素, UIView-Encapsulated-Layout-Height可能四舍五入到200.我提出的修复只是降低相关单元约束的优先级,以允许UIView-Encapsulated-Layout-Height具有最后一个单词。

这可能不会回答你的问题,但它可以帮助像我这样的人从search到这里。

我得到了一个奇怪的AutoLayout破碎的约束错误,伴随着一个UIView-Encapsulated-Layout-Width约束,因为我将一个tableHeaderView添加到尚未用AutoLayout进行大小调整的表视图中。 所以系统试图将我的头部子视图的约束应用于{0,0,0,0}框架的tableview中。 由于UITableView喜欢控制其元素的宽度,所以它生成的宽度约束UIView-Encapsulated-Layout-Width被设置为零,导致我期待的320 + pt宽度的头元素的各种混乱。

外卖:确保您在添加/操作您的补充/页眉/页脚视图后,通过AutoLayout调整桌面大小。

我在各种情况下得到这个错误(不一定与UICollectionView和朋友build立正确的答案)。

所以我处理这个问题的方法是简单地清除所有的约束,然后重新构build它们(只有这一次,我不担心我的约束与这些预先创build的约束相冲突):

所以在代码中:

 UIView *parentView = [viewInQuestion superview]; [parentView clearConstraintsOfSubview:viewInQuestion]; 

其中clearConstraintsOfSubview是UIView上的一个类别方法:

 - (void)clearConstraintsOfSubview:(UIView *)subview { for (NSLayoutConstraint *constraint in [self constraints]) { if ([[constraint firstItem] isEqual:subview] || [[constraint secondItem] isEqual:subview]) { [self removeConstraint:constraint]; } } } 

肯定在UITableViewtableHeaderView上看到这个。 我可以通过在设置tableHeaderView之后明确设置与tableView的宽度相等的宽度来使用自定义标题视图,然后在布局过程完成后重置它。

iOS 9的示例代码,假设您有一个UITableView作为tableView传递到您的方法,并将其configuration为item

 //Create the header view self.contentDetailHeaderView = MyCustomHeaderView() //Turn on autolayout self.contentDetailHeaderView.translatesAutoresizingMaskIntoConstraints = false //Add the header to the table view tableView.tableHeaderView = self.contentDetailHeaderView //Pin the width let widthConstraint = NSLayoutConstraint(item: self.contentDetailHeaderView, attribute: .Width, relatedBy: .Equal, toItem: tableView, attribute: .Width, multiplier: 1, constant: 0) tableView.addConstraint(widthConstraint) //Do whatever configuration you need to - this is just a convenience method I wrote on my header view. self.contentDetailHeaderView.setupForItem(item) //Lay out the configured view self.contentDetailHeaderView.layoutIfNeeded() //Reset the table header view, because ¯\_(ツ)_/¯ tableView.tableHeaderView = self.contentDetailHeaderView 

几个笔记,主要是当我再次看这个,因为我有一个金鱼的记忆:

  • 你不必从viewDidLayoutSubviews调用它 – 只要tableView在安装过程中有适当的宽度,我就可以使用这种技术。
  • 您需要确保您的标题视图设置为自动resize。 我通过创build一个.xib做到这一点,然后确保所有的项目被固定,以便当视图改变宽度时,高度将被更新。
  • 如果你想为viewForHeaderInSection做这viewForHeaderInSection ,那么你可能最好把屏幕外的东西viewForHeaderInSection ,这样你就可以viewForHeaderInSection 这个技巧 。 我没有太多的运气与自我大小的位。

我面对同样的奇怪的约束,不知道为什么,直到我记得translatesAutoresizingMaskIntoConstraints自动化MakesMaskIntoConstraints属性。 设置这个false解决了这个问题。 后台发生的事情是,自动resize的掩码(iOS的旧版式引擎)被转换为约束。 很多时候,你不想要这些限制,并想要自己的限制。 在这种情况下,你应该设置这个属性为false,你会没事的:

 view.translatesAutoresizingMaskIntoConstraints = false 

我们已经开始在iOS 11中看到大量的布局冲突,其中包括对这些约束的引用,事实上它们是通过translatesAutoresizingMaskIntoConstraints标志添加的。 看起来,在iOS 11中,当视图添加到层​​次结构中时,会发生更多的AutoLayout魔术,而不仅仅是布局视图(因为它似乎可以在以前的iOS版本中使用)。 这是我们遇到的情况: – 创build一个视图,其内部布局有助于定义视图大小(例如,视图有内部约束,包括显式填充等)
– ***将此视图添加到层​​次结构中。 – 在布局通过之前的一段时间,将translatesAutoresizingMaskIntoConstraints设置为false。

第二步(***)将导致冲突,因为在视图添加到层​​次结构时,系统将为视图添加零大小约束。 我们后来设置了translatesAutoresizingMaskIntoConstraints,这是因为使用了PureLayout框架,当你限制视图时,它会自动地设置这个标志…也就是说,在iOS 11中,你需要记住在构build时closurestranslatesAutoresizingMaskIntoConstraints到层次结构。

我怀疑苹果认为把这个标志默认为YES会比痛苦更有帮助。 不幸的是,情况并非如此。

我在iPad Pro上testing了拆分视图时发现了一个类似的问题,而DesignatedNerd的答案正常,但我并不需要太多的代码。 这是我用的:

 [self.tableView.tableHeaderView setTranslatesAutoresizingMaskIntoConstraints:NO]; NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeWidth multiplier:1 constant:0]; NSLayoutConstraint *yConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; [self.tableView addConstraints:@[widthConstraint, yConstraint]]; 

注意添加了Y Constraint,它将tableHeaderView的顶部绑定到tableView的顶部。

向表视图标题添加约束时,遇到同样的问题。 当头部的边界是(0,0,0,0)时,用set常量添加约束似乎会发生这种情况。 我设法解决这个问题,只是在布局子视图方法中添加约束时,头部的边界不是(0,0,0,0)

  if self.bounds == CGRect.zero { return }