嵌入 ViewController 时视图未按预期使用 AutoLayout 进行布局

Posted

技术标签:

【中文标题】嵌入 ViewController 时视图未按预期使用 AutoLayout 进行布局【英文标题】:Views not laying out as expected with AutoLayout while embedding a ViewController 【发布时间】:2013-07-26 00:25:11 【问题描述】:

我要做的事情看起来很简单,但我无法让事情说明我的期望。考虑到不同的屏幕尺寸时,我使用 AutoLayout 来避免硬编码帧。所有 .xib 的 AutoLayout 都已打开,但我没有在 Interface Builder 中创建任何显式约束。

ViewControllerA 正在嵌入 ViewControllerB 并将 VCB 的视图添加到它的视图层次结构中。 VCA 有一个 TableView,而 VCB 有一个 UserView(只是一个带有子视图的普通视图)。

我希望 TableView 位于 UserView 之上。 UserView 有一个固定的高度,它的底部将始终固定在屏幕的底部。 TableView 将填满屏幕的其余部分。

这是我在代码中的内容。这成功地将 UserView 粘到了底部:

userViewController.view.translatesAutoresizingMaskIntoConstraints = false;
NSDictionary *constrainedViews = @ @"userView" : userViewController.view, @"menu" : self.menuTable ;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[userView]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:constrainedViews]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[userView(174)]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:constrainedViews]];

1) 如果我在添加约束之前没有调用translatesAutoresizingMaskIntoConstraints,我会得到“无法同时满足约束”。在我的控制台中抱怨 NSAutoresizingMaskLayoutConstraints 冲突。为什么?我打开了自动布局。我认为只有在结合 AutoLayout 和非 AutoLayout 视图时才会出现此错误。是因为我在 IB 中没有设置明确的约束吗?

所以我根据需要将 UserView 与底部对齐,现在我想将 TableView 堆栈放在顶部并填充剩余的屏幕。如果我将上面的最后一个约束(垂直约束)替换为:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[menu][userView(174)]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:constrainedViews]];

我的控制台又出现一堆错误。

(
"<NSLayoutConstraint:0xd39c880 'IB auto generated at build time for view with fixed frame' V:|-(0)-[UITableView:0xe914e00]   (Names: '|':UIView:0xd39ea60 )>",
"<NSLayoutConstraint:0xd39c590 'IB auto generated at build time for view with fixed frame' V:[UITableView:0xe914e00(362)]>",
"<NSLayoutConstraint:0xd3a4f60 V:[UITableView:0xe914e00]-(0)-[UIView:0xd39ff60]>",
"<NSLayoutConstraint:0xd3a4350 V:[UIView:0xd39ff60]-(0)-|   (Names: '|':UIView:0xd39ea60 )>",
"<NSAutoresizingMaskLayoutConstraint:0xd3af6d0 h=-&- v=-&- UIView:0xd39ff60.midY == UIView:0xd39ea60.midY>"
)

我已经被困了几个小时,不知道如何继续。任何想法我做错了什么?为什么 IB 会自动生成一个固定帧,而我无法用我的新约束覆盖?

【问题讨论】:

“我没有在 Interface Builder 中创建任何显式约束”——事实上你没有创建它们并不意味着它们不是 Xcode 为你创建的。您可能需要修改在 IB 中为您创建的那些,或者删除它们并添加您自己的。 当我查看 ViewControllerA.xib 时,我的视图中唯一的东西是 UITableViewController。看起来没有应用任何约束。我还注销了[self.tableView constraints],它是一个空数组。 您使用的是什么版本的 Xcode?您是否关闭了自动布局? Xcode 5-DP3。我只知道如何在 .xib 中关闭自动布局,并且在我所有的 .xib 中都打开了。 我不是在询问任何特定于 NDA 内容的内容。自动布局早于 Xcode 5,这就是我的问题所关注的。 【参考方案1】:

看起来损坏的约束在您的超级视图或包含 UITableView 的视图上,而不是在 UITableView 本身上。如果您打算在代码中设置这些约束,则应首先删除所有这些自动约束:

[self.view removeConstraints:self.view.constraints];

【讨论】:

哇,谢谢。与我见过的所有其他示例相比,这很简单,人们在 Interface Builder 中添加约束,然后选中“在构建时删除”占位符复选框。 如果您的所有约束都在代码中进行管理,并且您可以从视图中删除所有内容,则此方法可以正常工作。但是,如果您有任何想要保留的界面构建器约束,则必须采用添加约束并将它们标记为占位符的方法。我发誓,Apple 在这个设计上丢了球。真是一团糟。 @devios ,但是如果您将它们标记为占位符,它们在运行时不会随时生效。那么为什么不通过代码删除它们呢? @roimulia 我的意思是,如果你想保留一些限制,那就更难了。 @devios it his ,我在构建时自动生成了这个奇怪的 IB,用于查看固定 frame.marker 崩溃和更多此类问题。所以我从 VC 中删除了所有约束,但仍然崩溃。有什么想法吗?

以上是关于嵌入 ViewController 时视图未按预期使用 AutoLayout 进行布局的主要内容,如果未能解决你的问题,请参考以下文章

嵌入在 UITableView 中的 UICollectionView 中的 UICollectionViewCells 未按预期显示

navigationController?.navigationBar.isUserInteractionEnabled 未按预期工作

以编程方式修改 ConstraintSet 链未按预期工作

QGraphicsView 滚动条策略未按预期工作

未按预期应用约束

UI 滚动视图未按预期滚动