2

我想以编程方式做一个简单的布局,但我想念一些简单的东西,或者有一些不合适的东西。下面的 ViewController 应该在超级视图中将标签居中。但是,它会因这条修剪消息而崩溃:The view hierarchy is not prepared for the constraint ... 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... View not found in container hierarchy: ... That view's superview: NO SUPERVIEW带有此错误消息的其他 SO 问题大部分都使用 nibs,我试图避免这种情况,或者使用Obj-C而不是swift. 这个问题有点涉及这个话题,但有点老了。

谁能指出我正确的方向?

class ViewController: UIViewController {
let label1 = UILabel() as UILabel

func layoutView(){

    label1.text = "Click to see device configuration"
    label1.setTranslatesAutoresizingMaskIntoConstraints(false)
    view.addSubview(label1)
    let viewsDictionary = ["label1":label1]

    let label1_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label1]-|",
        options: NSLayoutFormatOptions(0),
        metrics: nil,
        views: viewsDictionary)

    let label1_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[label1]-|",
        options: NSLayoutFormatOptions(0),
        metrics: nil, views:
        viewsDictionary)

    label1.addConstraints(label1_H) // Comment these 2 lines and it runs, but
    label1.addConstraints(label1_V) // of course the label is upper left

}

override func viewDidLoad() {
    super.viewDidLoad()
    layoutView()
}
}
4

2 回答 2

4

这些约束是在标签和它的超级视图之间建立的。约束应该添加到该超级视图,而不是标签。

于 2014-09-22T00:09:00.367 回答
3

您快到了。只需替换以下几行...

label1.addConstraints(label1_H) // Comment these 2 lines and it runs, but
label1.addConstraints(label1_V) // of course the label is upper left

...使用以下代码:

view.addConstraints(label1_H) // Comment these 2 lines and it runs, but
view.addConstraints(label1_V) // of course the label is upper left

但是,约束H:|-[label1]-|"V:|-[label1]-|"等价于H:|-8-[label1]-8-|"V:|-8-[label1]-8-|"(有关默认边距的更多详细信息,请参阅iOS 开发人员库)。因此,这些约束并不意味着您的标签居中。实际上,您将拥有一个巨大的标签,该标签具有 8 个单元的顶部、前导、尾随和底部边距到 viewController 的视图。

在您的方法中添加以下代码行layoutView()以了解我的意思:

label1.backgroundColor = UIColor.orangeColor()

可以,但是如果您真的想将标签居中,则必须使用以下代码:

func layoutView() {
    label1.text = "Click to see device configuration"
    label1.backgroundColor = UIColor.orangeColor()
    //Set number of lines of label1 to more than one if necessary (prevent long text from being truncated)
    label1.numberOfLines = 0

    label1.setTranslatesAutoresizingMaskIntoConstraints(false)
    view.addSubview(label1)

    let xConstraint = NSLayoutConstraint(item: label1,
        attribute: NSLayoutAttribute.CenterX,
        relatedBy: NSLayoutRelation.Equal,
        toItem: view,
        attribute: NSLayoutAttribute.CenterX,
        multiplier: 1.0,
        constant: 0.0)
    self.view.addConstraint(xConstraint)

    let yConstraint = NSLayoutConstraint(item: label1,
        attribute: NSLayoutAttribute.CenterY,
        relatedBy: NSLayoutRelation.Equal,
        toItem: view,
        attribute: NSLayoutAttribute.CenterY,
        multiplier: 1.0,
        constant: 0)
    self.view.addConstraint(yConstraint)

    //Add leading and trailing margins if necessary (prevent long text content in label1 to be larger than screen)
    let viewsDictionary = ["label1" : label1]
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(>=10@750)-[label1]-(>=10@750)-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary))
}
于 2014-09-22T01:01:52.060 回答