82

我有一个自定义 UIView 子类,它正在通过 nib 初始化。

-awakeFromNib中,我正在创建一个子视图并尝试将其置于其父视图的中心。

[self setInteralView: [[UIView alloc] init]];
[[self internalView] addConstraint: [NSLayoutConstraint constraintWithItem: [self internalView]
                                                                 attribute: NSLayoutAttributeCenterX
                                                                 relatedBy: NSLayoutRelationEqual
                                                                    toItem: self
                                                                 attribute: NSLayoutAttributeCenterX
                                                                multiplier: 1
                                                                  constant: 0]];

这会中断,并导致以下输出:

2013-08-11 17:58:29.628 MyApp[32414:a0b] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2013-08-11 17:58:29.630 MyApp[32414:a0b] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    Container hierarchy: 
<UIView: 0xc132a40; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0xc132bc0>>
    View not found in container hierarchy: <MyView: 0xc1315a0; frame = (-128 -118; 576 804); layer = <CALayer: 0xc131710>>
    That view's superview: <UIView: 0xc131a70; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xc131b50>>
4

8 回答 8

117

对于来到这里的其他人:我收到此错误,因为我在将子视图添加到层​​次结构之前添加了约束。

于 2014-07-29T17:21:05.790 回答
95

如错误所述,您必须将约束添加到视图中,以便约束中涉及的视图是您将其添加到的视图或该视图的子视图。对于上面的代码,您应该将该约束添加到self,而不是[self internalView]. 它不能按书面形式工作的原因是约束中涉及的视图之一 ( self) 不在视图层次结构中,如果您只考虑[self internalView]以下内容)。

有关更多详细信息,请参阅有关该方法的文档的讨论部分。addConstraint:

这是您的代码行,按照我的建议进行了修复:

UIView* internalView = [[UIView alloc] initWithFrame:CGRectZero];
internalView.translatesAutoresizingMaskIntoConstraints = NO;
[self setInternalView:internalView];

[self addConstraint: [NSLayoutConstraint constraintWithItem: [self internalMapView]
                                         attribute: NSLayoutAttributeCenterX
                                         relatedBy: NSLayoutRelationEqual
                                         toItem: self
                                         attribute: NSLayoutAttributeCenterX
                                         multiplier: 1
                                         constant: 0]];
于 2013-08-11T22:23:32.423 回答
36

简短回答交换父子视图。
假设self是父视图:

  • [subview addConstraint [NSLayoutConstraint constraintWithItem:self...

  • [self addConstraint [NSLayoutConstraint constraintWithItem:subview...


迅速

subview.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
    "H:|-0-[subview]-0-|",
    options: .DirectionLeadingToTrailing,
    metrics: nil,
    views: ["subview":subview]))

对象-C

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addConstraints:[NSLayoutConstraint
                      constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                      options:NSLayoutFormatDirectionLeadingToTrailing
                      metrics:nil
                      views:NSDictionaryOfVariableBindings(subview)]];
于 2015-07-23T05:39:38.980 回答
10

附加提示:

我有一个新开发的应用程序,它在 iOS7 上运行良好,但在 iOS8 上出现错误“视图层次结构没有为约束做好准备”。

阅读其他一些帖子说需要在创建约束之前添加(子)视图。我这样做了,但仍然出现错误。

然后我发现我应该在 -(void)viewDidAppear 而不是 viewDidLoad 下创建约束

于 2015-05-19T16:54:40.037 回答
6

这是一个老问题,但我想从文档中指出这一行:

在为 iOS 8.0 或更高版本开发时,将约束的 isActive 属性设置为 true,而不是直接调用 addConstraint(_:) 方法。isActive 属性会自动在正确的视图中添加和删除约束。

至少,这将消除一个故障点,因为您不再需要担心在错误的视图上调用 addConstraint

于 2017-05-25T21:23:46.427 回答
2

就我而言,它是通过使用根视图作为约束容器而不是当前创建的视图来解决的。

我的意思是,在 viewController 内部使用

view.addConstraints([leftConstraintImage, topConstraintImage]) 代替imageView.addConstraints...

于 2018-05-10T21:45:03.877 回答
1

正如@CharlesA 在他的回答中指出的那样,问题在于您添加的视图不在正确的视图层次结构中。他的回答很好,但我将详细介绍导致我遇到此问题的特定用例:

当我尝试将约束添加到我使用instantiateViewControllerWithIdentifier. 为了解决这个问题,我使用了[childViewController didMoveToParentViewController:self]. 这会将视图添加到我的约束引用的视图层次结构中。

于 2014-06-29T15:23:19.383 回答
0

首先添加您的子视图,然后像这样添加您的约束

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false

addConstraint(NSLayoutConstraint(....
于 2019-09-27T10:52:28.187 回答