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


74

我的布局约束在Interface Builder中很好,但是由于框架的某些部分应用了我确实不希望的固定高度和宽度约束,因此在运行时发生了异常。他们为什么在那里,以及如何将它们关闭?

它们是已记录列表中显示的最后两个约束:

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>

Answers:


95

基于一吨的观察,我相信(但不能确切知道)的约束命名UIView-Encapsulated-Layout-Width,并UIView-Encapsulated-Layout-Height通过创建UICollectionView和朋友,存在以执行返回的大小sizeForItemAtIndexPath委托方法。我想这是为了确保UICollectionViewCellby的设置cellForItemAtIndexPath最终会达到所要求的大小。

哪一个回答了我最初的问题。第二个问题是为什么约束条件不能令人满意?像元的固有高度应与相同UIView-Encapsulated-Layout-Height。同样,我不确定,但是我怀疑这是一个舍入误差(即,固有高度为200.1像素,UIView-Encapsulated-Layout-Height可能舍入为200。我想出的解决办法是降低相关单元格约束的优先级允许UIView-Encapsulated-Layout-Height有硬道理。


1
美丽。修复了我项目中的类似问题。
Jamie Forrest 2014年

2
这个固定我的约束破损和相应的警告信息,但现在我的文本视图处于折叠状态,直到我滚动单元出来查看,然后回。
Alex311

1
@ Alex311您是否尝试过在IB中调整抗压强度(或其他名称)?我发现增加此值有助于防止文本崩溃
Orion Edwards

1
除此之外,我UIView-Encapsulated-Layout-Width在8.3设备中遇到了类似的问题,并想起了有关此推文的信息。致电[someView layoutIfNeeded]有助于解决问题。
罗德里戈·利马

11
我完全没有希望在控制台中修复约束警告,但是不知何故,我又遇到了另一个约束问题,这导致我进入此页面,我很高兴来到这里并查看您的回答。我只是将优先级降低到999,但我的所有约束警告都消失了:)非常感谢:) :) :)
Srikanth

45

这可能无法回答您的问题,但可以帮助像我这样从搜索中来到这里的其他人。

我收到一个奇怪的AutoLayout打破约束错误并伴有UIView-Encapsulated-Layout-Width约束,因为我正在向tableHeaderView尚未使用AutoLayout调整大小的表视图中添加。因此系统尝试将我的标头子视图的约束应用于具有框架的表视图内{0,0,0,0}。由于UITableView喜欢控制其元素的宽度,因此将其生成的宽度约束(UIView-Encapsulated-Layout-Width)设置为零,从而与我期望320 + pt宽度的标头元素引起各种混乱。

要点:确保在通过AutoLayout调整了表格视图的大小之后,添加/操作了补充/页眉/页脚视图。


2
我想确定自己做得正确。您能解释一下如何确定这些操作在自动版面设计之后发生吗?
nwales

3
@nwales当iOS尝试在0 x 0视图内布局约束时,会出现问题。为避免此错误,只需确保容器视图(在我的情况下为tableHeaderView)已布置好或已手动调整大小。您可以通过在设置约束之前用一个近似的大小初始化容器视图来完成此操作,或者如果您想纯粹的自动布局,请对容器视图的约束进行布局,然后[thatContainer layoutIfNeeded]在设置子视图约束之前调用。如果没有收到错误并且您的观点是直截了当的,那么您就不必担心。
Yerk 2015年

谢谢!翻转我布置表格视图并分配其表头的顺序会使此错误消失=)
CodeMonkey

最好的解决方案是删除约束的优先级,这样就不需要它们了。将高优先级放在优先位置。
亚历山大·史密斯

6

我一直面临着同样的怪异约束,不知道为什么,直到我想起了织补 translatesAutoresizingMaskIntoConstraints财产。进行设置以false解决问题。在后台发生的事情是将自动调整大小的蒙版(iOS的旧版布局引擎)转换为约束。通常,您不需要这些约束,而需要自己的约束。在这种情况下,应将此属性设置为false,这样就可以了:

view.translatesAutoresizingMaskIntoConstraints = false

2
view您到底要在哪设置?是UITableViewCell吗?
Hlung

通常,您将在要添加的视图上进行设置。
佐尔坦

4

在清楚看到这个UITableViewtableHeaderView。我可以通过将宽度显式设置为等于设置后的宽度,来与自定义标题视图一起tableView使用tableHeaderView,重新那么它的布局传递完成之后。

iOS 9的示例代码,假设您已将UITableView方法传递为tableView并且将其配置为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有安装过程中适当的宽度。
  • 您需要确保将标题视图设置为自动调整自身大小。为此,我创建了一个.xib ,然后确保所有项目都被固定,以便在视图更改宽度时,高度将随之更新。
  • 如果您为此做尝试viewForHeaderInSection,那么最好抓住屏幕外的东西,这样可以布置这种技术。我对自动调整位没有什么运气。

哇。经过半个小时的混乱...这实际上有效!我不明白为什么需要它,但是它有效。不幸的是,我们必须这样做。
约里斯·芒斯

4

我们已经开始在iOS 11中看到大量的布局冲突,其中包括对这些约束的引用,实际上它们是通过 translatesAutoresizingMaskIntoConstraints标志。似乎在iOS 11中,将视图添加到层​​次结构中时,而不是仅在布局视图时,发生了更多的AutoLayout魔术(因为它似乎在以前的iOS版本中有效)。

这是我们遇到的情况:

  • 创建一个其内部布局有助于定义视图大小的视图(例如,该视图具有内部约束,其中包括显式填充等)
  • ***将此视图添加到层​​次结构中。
  • 在布局通过之前的一段时间之后,将translatesAutoresizingMaskIntoConstraints设置为false。

第二步(***)将导致冲突,因为在将视图添加到层​​次结构时,系统将向视图添加零大小约束。我们translatesAutoresizingMaskIntoConstraints稍后进行设置的原因是使用了PureLayout框架,该框架会在您约束视图时自动正确设置此标志...也就是说,在iOS 11中,您需要记住translatesAutoresizingMaskIntoConstraints在构造时关闭视图,然后再将视图添加到视图中。层次结构。

我怀疑苹果公司认为将此标志默认为YES会比痛苦更有用。不幸的是,情况并非如此。


PureLayout提供initForAutoLayoutnewAutoLayoutView设置translatesAutoresizingMaskIntoConstraints为false的初始化程序,可以在ALView子类上调用它们
killianke

3

我在各种情况下都收到此错误(不一定正确地建议与UICollectionView和朋友联系在一起)答案的)。

因此,我的处理方式是清除所有约束,然后再次构建它们(仅这次,我不担心约束与这些预先创建的约束发生冲突):

所以在代码中:

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

clearConstraintsOfSubviewUIView上的类别方法在哪里:

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

2

我遇到了类似的问题,并通过以下方法解决了这个问题。

  • 环境: Swift 5.0,xcode 10.2.1,以编程方式设置视图

  • 警告消息:无法同时满足约束条件...'UIView-Encapsulated-Layout-Width'UIView:0x0000000000.width == 0(active)>“)

  • 带有警告的代码

    override func loadView() {
    
    view = UIView()
    
    /// Adds the subviews to the view and sets their properties and constraints
    setupViews()
    
    }
    
  • 清除警告的代码

    override func loadView() {
    
    /// Needed to set the frame of the root view to the window frame.
    let window = UIWindow()
    view = UIView(frame: window.frame)
    
    /// Adds the subviews to the view and sets their properties and constraints
    setupViews()
    }
    
  • 关于loadView()方法的注释: “如果使用Interface Builder创建视图并初始化视图控制器,则不能覆盖此方法。可以覆盖此方法以手动创建视图。如果选择这样做, ,将视图层次结构的根视图分配给view属性。您创建的视图应该是唯一的实例,并且不应与任何其他视图控制器对象共享。此方法的自定义实现不应调用super。” -Apple文档

  • 关于根视图的注释:

    “如果您希望以编程方式创建视图,则可以通过重写视图控制器的loadView方法来实现。此方法的实现应执行以下操作:

    创建一个根视图对象。根视图包含与视图控制器关联的所有其他视图。通常,您需要为此视图定义框架以匹配应用窗口的大小,而应用窗口本身应填满屏幕。但是,将根据视图控制器的显示方式来调整框架。请参阅“ View Controller视图调整大小”。

    您可以使用通用的UIView对象,定义的自定义视图或任何其他可以缩放以填充屏幕的视图。

    创建其他子视图并将其添加到根视图。”-旧的Apple文档?


2

敲了一下头后,我发现了这个联系。就我而言,这是在我使用UIVieController中的insertRows或deleteRows时在UITableViewHeaderFooterView上发生的。设置了“ estimatedSectionHeaderHeight”和“ estimatedRowHeight”,我的约束重做了3次……显示的错误是:

"<NSLayoutConstraint:0x280648140 H:|-(8)-[UIImageView:0x106e94860]   (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>",
"<NSLayoutConstraint:0x280648230 H:[UIImageView:0x106e94860]-(8)-[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']   (active)>",
"<NSLayoutConstraint:0x280648410 H:[UIButton:0x106ea5a40]-(8)-|   (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>",
"<NSLayoutConstraint:0x280648460 H:[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']-(8)-[UIButton:0x106ea5a40]   (active)>",
"<NSLayoutConstraint:0x2806493b0 'UIView-Encapsulated-Layout-Width' DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50.width == 0   (active)>"

如链接上所述:

当您使用某些动画类型来执行insertRows或deleteRows时,UIKit会将行高设置为从0到全高或全高的动画。在该动画的0端,如果将整个垂直轴设置为优先级,则无法求解布局方程式= 1000。但是只需将一个约束降低到999(例如,底部空间到超级视图边距),一切都很好;内容将在单元格边界之外下拉

解决方案是将UIImageView的领先优先级设置为999(或降低到1000)。


1

就我而言,我无意中设置了两次编程约束。我删除重复的通话后,冲突就消失了。


1

我在使用AL创建tableviewHeader时遇到了这个问题

我像下面那样初始化tableview

let table = UITableView.init(frame: .zero, style: .grouped)
// set table constraint ...

然后我用AutoLayout创建tableviewHeader。

"<NSLayoutConstraint:0x600003d7d130 'UIView-Encapsulated-Layout-Width' UIView:0x7fe92bc55260.width == 0 (active)>"

出现符号断点

在我引用@Yerk的答案之后。我初始化tableView时更改框架

let rect = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 0)
let table = UITableView.init(frame:rect , style: .grouped)

问题似乎已经解决



0

在iPad Pro上测试Split View时,我遇到了类似的问题,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约束”,该约束将tableHeaderView的顶部绑定到tableView的顶部。


0

向表视图标题添加约束时,我遇到了同样的问题。当标头的边界为(0,0,0,0)时,使用设置常量添加约束时,似乎会发生这种情况。我设法通过仅在标头的边界不为(0,0,0,0)时在layout subviews方法中添加约束来解决此问题

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

0

UIView-Encapsulated-Layout-Height使用您在其中设置的值创建约束tableView.estimatedSectionHeaderHeight

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.