Ограничения VFL в swift: Сбои из-за отсутствия супервизора
Я пытаюсь сделать простую компоновку программно, и мне не хватает чего-то простого, или я думаю, что-то неуместное. Следующий 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 с этим сообщением об ошибке по большей части используют перья, и я стараюсь этого избегать, или использую 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()
}
}
2 ответа
Эти ограничения сделаны между лейблом и его суперпредставлением. Ограничения должны быть добавлены к этому суперпредставлению, а не к метке.
Ты почти там. Просто замените следующие строки...
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))
}