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

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

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

person prawn    schedule 08.04.2016    source источник
comment
Почему бы вам не использовать для этого язык визуального формата? "H:[panel(300)]| и "V:|[toplayout][panel][botlayout]|" должно хватить.   -  person Eendje    schedule 08.04.2016


Ответы (3)


На самом деле проблема в вашем коде заключается в том, что вы не установили 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))
person keshav vishwkarma    schedule 08.04.2016
comment
Если вам нужен более простой способ программного добавления ограничений, используйте github.com/keshavishwkarma/KVConstraintExtensionsMaster. - person keshav vishwkarma; 10.04.2016

В приведенном выше примере кода кажется, что вы смешиваете 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/

person Daniel Hall    schedule 08.04.2016

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

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

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

person Arun Gupta    schedule 08.04.2016