Программно создавая ограничения, связанные с просмотром полей контроллера

Я пытаюсь сделать представление, которое будет действовать как своего рода "панель", прикрепленная к правой стороне контроллера вида.

То есть он привязан к верхнему и нижнему полям родительского контроллера просмотра, со статической шириной 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 также является лучшим и чистым подходом. Фактически это дает визуализацию настройки ограничений.