iOS 程序约束:“在容器层次结构中找不到视图”

Posted

技术标签:

【中文标题】iOS 程序约束:“在容器层次结构中找不到视图”【英文标题】:iOS Programatic Constraints: 'View not found in container hierarchy' 【发布时间】:2015-01-21 17:12:19 【问题描述】:

我的 ios 自定义 UITableViewCell 需要以下布局:

|查看基本信息 |长长的矩形视图列表 |

所以,结构如下。我有一个水平滚动的滚动视图,左侧有“信息容器视图”,矩形视图列表应该出现在信息容器的右侧。自定义 UITableViewCell 是 o

我试图添加以下约束:

[self.scrollView addConstraints:[NSLayoutConstraint
                                             constraintsWithVisualFormat:[NSString stringWithFormat:@"H:[info]-space-[%@]", key]
                                             options:0 metrics:metrics
                                             views:viewsDictionary]];

其中 info 是“信息容器”,“key”是指动态添加的视图。这会导致以下错误:

2015-01-21 16:37:44.603 AirCourts[3264:1553444] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x174a83840 H:[UIView:0x17018f970]-(20)-[FieldSlotView:0x1701bebc0]>
Constraint: <NSLayoutConstraint:0x174a83840 H:[UIView:0x17018f970]-(20)-[FieldSlotView:0x1701bebc0]>
(...)
View not found in container hierarchy: <UIView: 0x17018f970; frame = (0 0; 320 568); autoresize = RM+BM; layer = <CALayer: 0x170e37c20>>
That view's superview: NO SUPERVIEW

所以,它似乎是指“信息容器”没有超级视图的事实。因此,我决定对其进行测试:

如您所见,它不被假定为滚动视图的后代。鉴于 IB 层次结构似乎是正确的,为什么会发生这种情况?由于某种原因,我是否需要在添加约束之前刷新布局,或者它是否会丢失层次结构信息?

提前致谢!

【问题讨论】:

您是否在 viewDidLoad 中检查后代控制器?您应该在 ViewDidLayoutSubviews 或之后调用它,而不是在此之前。 【参考方案1】:

在我看来,您收到该错误是因为“动态加载的视图”不是scrollView 的直接子代,而是infoView 的直接子代。

因此,为了让 AutoLayout 在这里工作,您宁愿将该约束附加到它的父视图,它应该是 infoView,而不是 scrollView

从日志中可以看出,您的 infoView 是 [UIView:0x17018f970],AutoLayout 会尝试在其层次结构下找到您的 [FieldSlotView:0x1701bebc0]。这就是为什么您会收到以下错误View not found in container hierarchy: &lt;UIView: 0x17018f970&gt;

小提示

将约束附加到视图时,您可以在约束字符串中以| 的形式访问它。因此,如果您将代码替换为

[self.infoView addConstraints:[NSLayoutConstraint
                                             constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-space-[%@]", key]
                                             options:0 metrics:metrics
                                             views:viewsDictionary]];

您可以将[info] 替换为| ;)

【讨论】:

嗨,迈克,感谢您的回复!我的想法是动态视图(我们称它们为“字段”)是 infoView 的兄弟姐妹。实际上,我使用 infoView 能够说“字段”在布局方面将位于 infoView 的右侧(因此受到限制)。【参考方案2】:

对于 iOS 8.0+,Apple 建议简单地激活/停用约束更安全。他们将处理受影响的视图。

比如说你已经声明了

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *constraintProperty;

然后在你的代码中的某个地方:

[_constraintProperty setActive:NO];

// create constraint here

[NSLayoutConstraint activateConstraints:@[_constraintProperty]];

参见文档中的讨论:

https://developer.apple.com/documentation/uikit/uiview/1622513-addconstraints https://developer.apple.com/documentation/uikit/uiview/1622659-removeconstraint

【讨论】:

以上是关于iOS 程序约束:“在容器层次结构中找不到视图”的主要内容,如果未能解决你的问题,请参考以下文章

UIView 事件应用约束并设置子视图宽度

堆栈视图中的自动约束冲突、Swift 2、iOS 9.3、XCode 7

XCode 6.4 中 iOS8 Storyboard 中缺少约束图标,适用于最初在早期版本的 iOS 下编写的应用程序

iOS 8 约束

使用手动约束的自动布局[关闭]

iOS 8 Xcode 6:使用顶部/底部布局指南进行顶部/底部约束时,应用程序始终崩溃