以编程方式创建约束以查看控制器边距

Programmatically creating constraints bound to view controller margins

我正在尝试创建一个视图,作为一种 "panel",附加到视图控制器的右侧。

即绑定父视图控制器的尾边距、上边距和下边距,静态宽度为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])

您的代码中似乎存在一些歧义,您正在创建一个 UIView 作为 myView 但将视图添加到 self.view 甚至约束也可以查看自身。因此,更正您的代码并将视图替换为 myView。 其次setTranslayesAutoresizingMaskIntoConstraints为false。 然后将所有约束添加到self.view。这应该可以解决您的问题。

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

VFL 也是一种更好、更干净的方法。它实际上给出了如何设置约束的可视化。

在上面的示例代码中,您似乎在一些地方混淆了 viewmyView。在任何情况下,widthConstraint 应添加到 myViewtopConstrainttrailingConstraintbottomConstraint 应添加到 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/

实际上你的代码中的问题是你没有将 myviewtranslatesAutoresizingMaskIntoConstraints 设置为 false,每当你想使用自动布局约束时,你必须设置translatesAutoresizingMaskIntoConstraints 的一个视图为false。 另一个问题是你没有在 self.view 上添加 myview 我已经更新了你的代码并且它工作正常根据你的限制。

将以下代码放入您的 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))