Программно создавая ограничения, связанные с просмотром полей контроллера
Я пытаюсь сделать представление, которое будет действовать как своего рода "панель", прикрепленная к правой стороне контроллера вида.
То есть он привязан к верхнему и нижнему полям родительского контроллера просмотра, со статической шириной 300
Однако я просто не могу понять, что я прав, я либо нарушаю ограничение, либо делаю что-то, что xcode говорит мне, что это незаконно.
Что я делаю неправильно?
Вот код в контроллере
let myView = UIView()
view.backgroundColor = UIColor.redColor()
self.view.addSubview(view)
let topConstraint = NSLayoutConstraint(item: myView,
attribute: .Top,
relatedBy: .Equal,
toItem: self.topLayoutGuide,
attribute: .Bottom,
multiplier: 1,
constant: 0)
let trailingConstraint = NSLayoutConstraint(item: self.view,
attribute: .TrailingMargin,
relatedBy: .Equal,
toItem: myView,
attribute: .Trailing,
multiplier: 1,
constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.bottomLayoutGuide,
attribute: .Top,
relatedBy: .Equal,
toItem: myView,
attribute: .Bottom,
multiplier: 1,
constant: 0)
let widthConstraint = NSLayoutConstraint(item: myView,
attribute: .Width,
relatedBy: .Equal,
toItem: nil,
attribute: .NotAnAttribute,
multiplier: 1,
constant: 300)
self.view.addConstraints([trailingConstraint])
view.addConstraints([topConstraint, bottomConstraint, widthConstraint])
Ответы
Ответ 1
На самом деле проблема в вашем коде заключается в том, что вы не устанавливали translatesAutoresizingMaskIntoConstraints
от myview
до false
, всякий раз, когда вы хотите использовать ограничения автомакета, тогда вы должны установить translatesAutoresizingMaskIntoConstraints
для представления в false,
Другая проблема заключается в том, что вы не добавляете myview
на self.view. Я обновил ваш код и его работоспособность. По вашим ограничениям.
Поместите ниже код в свой ViewController.
let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)
myView.translatesAutoresizingMaskIntoConstraints = false
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute:.Top, multiplier: 1, constant: 20))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute,multiplier: 1, constant: 300))
view.addConstraint(NSLayoutConstraint(item: myView, attribute: .TrailingMargin, relatedBy: .Equal, toItem: view, attribute: .TrailingMargin, multiplier: 1, constant: 0))
Ответ 2
В приведенном выше примере кода кажется, что вы смешиваете view
и myView
в нескольких местах. В любом случае widthConstraint
следует добавить в myView
и topConstraint
, trailingConstraint
, а bottomConstraint
следует добавить в self.view
. Причиной этого являются ограничения, которые должны быть добавлены к ближайшему предку предка, который определяет оба представления, связанные с этим ограничением. В случае, когда вы привязываете атрибут дочернего представления к атрибуту в его родительском представлении, ограничение должно быть добавлено к родительскому представлению, поскольку оно отображает как сам, так и дочерний вид. Если у вас есть ограничение между двумя представлениями sibling, ограничение будет добавлено к их родительскому представлению, поскольку оно является ближайшим предком, который определяет оба рассматриваемых представления.
Если вы можете настроить таргетинг на iOS 9.0 и выше, гораздо проще и проще использовать новый API NSLayoutAnchor и NSLayoutDimension для создания таких ограничений. Он также обеспечивает строгую проверку типов, и компилятор может проверить правильность. С помощью этих новых API, ваш пример кода просто станет:
let myView = UIView()
myView.backgroundColor = UIColor.redColor()
self.view.addSubview(myView)
let margins = self.view.layoutMarginsGuide
myView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
myView.topAnchor.constraintEqualToAnchor(margins.topAnchor).active = true
myView.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor).active = true
myView.widthAnchor.constraintEqualToConstant(300.0).active = true
Не нужно явно добавлять ограничения в правильное представление и т.д. Вы можете узнать больше об этом методе создания ограничений здесь:
https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/
и здесь:
https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutDimension_ClassReference/
Ответ 3
В коде есть какая-то двусмысленность, вы создаете UIView как myView, но добавляете представление в self.view и даже ограничение также для просмотра самого себя. Поэтому исправьте свой код и замените вид на myView.
Во-вторых, setTranslayesAutoresizingMaskIntoConstraints - false.
Затем добавьте все ограничения в self.view. Это должно решить вашу проблему.
myView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addConstraints([trailingConstraint, bottomConstraint, widthConstraint])
VFL также является лучшим и чистым подходом. Фактически это дает визуализацию настройки ограничений.