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

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

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

3 ответа

Решение

На самом деле проблема в вашем коде в том, что вы не установили translatesAutoresizingMaskIntoConstraints из myview в falseвсякий раз, когда вы хотите использовать ограничения автоматического размещения, вы должны установить translatesAutoresizingMaskIntoConstraints зрения ложного. Другая проблема в том, что вы не добавляете 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))

В приведенном выше примере кода кажется, что вы путаете view а также myView в нескольких местах. В любом случае, widthConstraint должны быть добавлены к myView а также topConstraint, trailingConstraint, а также bottomConstraint должны быть добавлены к self.view, Причина этого заключается в том, что ограничения должны быть добавлены к ближайшему предку суперпредставления, в котором изложены оба представления, вовлеченные в ограничение. В случае, когда вы ограничиваете атрибут дочернего представления атрибутом в его родительском представлении, ограничение должно быть добавлено к родительскому представлению, поскольку оно размещает и себя, и дочернее представление. Если у вас есть ограничение между двумя одноуровневыми представлениями, то ограничение будет добавлено к их родительскому представлению, поскольку именно ближайший предок размещает оба задействованных представления.

Если вы можете использовать iOS 9.0 и выше, гораздо проще и проще использовать новые NSLayoutAnchor и NSLayoutDimension API для создания подобных ограничений. Он также обеспечивает строгую проверку типов, и компилятор может проверить правильность. С этими новыми 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/

Кажется, в вашем коде есть некоторая двусмысленность: вы создаете UIView как myView, но добавляете представление в self.view и даже ограничиваете также для просмотра самого себя. Поэтому исправьте свой код и замените представление на myView. Во-вторых, установите значение falseTranslayesAutoresizingMaskIntoConstraints. Затем добавьте все ограничения в self.view. Это должно решить вашу проблему.

 myView.setTranslatesAutoresizingMaskIntoConstraints(false)
 self.view.addConstraints([trailingConstraint, bottomConstraint, widthConstraint])

VFL также лучший и чистый подход. Это фактически дает визуализацию того, как устанавливаются ограничения.

Другие вопросы по тегам