在autolayout中居中子视图的X会抛出“没有为约束做好准备”

时间:2013-08-11 22:18:49

标签: ios objective-c autolayout nslayoutconstraint uiview-hierarchy

我有一个自定义的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>>

7 个答案:

答案 0 :(得分:115)

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

答案 1 :(得分:91)

当错误指出时,您必须将约束添加到视图中,以使约束中涉及的视图是您要将其添加到该视图的子视图或该视图的子视图。对于上面的代码,您应该将该约束添加到self,而不是[self internalView]。它没有按照书面形式工作的原因是,如果仅考虑self及以下),约束中涉及的视图之一([self internalView])不在视图层次结构中。

有关详细信息,请参阅addConstraint:方法上的discussion section of the documentation

以下是您的代码行,按照我的建议修复:

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]];

答案 2 :(得分: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]))

<强>的OBJ-C

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addConstraints:[NSLayoutConstraint
                      constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                      options:NSLayoutFormatDirectionLeadingToTrailing
                      metrics:nil
                      views:NSDictionaryOfVariableBindings(subview)]];

答案 3 :(得分:10)

其他提示:

我有一个新开发的App,它在iOS7上运行良好,但在iOS8和#34上出错;视图层次结构没有为约束做好准备&#34;。

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

然后我发现我应该在 - (void)viewDidAppear而不是viewDidLoad

下创建约束

答案 4 :(得分:4)

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

  

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

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

答案 5 :(得分:1)

正如@CharlesA在他的回答中指出的那样,问题是您添加的视图不在正确的视图层次结构中。他的答案很好,但是我会针对一个特定的用例提出一些细节,这个用例会给我带来这个问题:

尝试向我的视图控制器使用instantiateViewControllerWithIdentifier实例化的视图添加约束时发生了这种情况。为了解决这个问题,我使用了[childViewController didMoveToParentViewController:self]。这将视图添加到我的约束引用的视图层次结构中。

答案 6 :(得分:0)

首先添加您的subView,然后添加这样的约束

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false

addConstraint(NSLayoutConstraint(....