我有一个NSView的子视图(比如MainView),其中有NSTextField。
注:此代码基于此github.repo
MainView已指定初始化器如下

init(title : String, layout :NSLayoutAttribute) {
    innerView = self.createTextField(title)//Text field with stringValue = title
    mainView.addSubview(innerView)
    createViewConstrants(innerView, layout: layout)
}

布局可以是LeftRightCenterX
(内部文本视图将始终垂直居中,只有水平对齐方式可以改变)
以下函数为此目的进行约束
func createViewConstrants(view : NSView, layout :NSLayoutAttribute) {

    let viewMap = ["innerView" : view, "superview" : mainView]
    var constraints :[AnyObject]!

    switch layout {
    case .Left:
        println("Left")
        constraints = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:[superview]-(<=1)-[innerView]",
            options: NSLayoutFormatOptions.AlignAllCenterY,
            metrics: nil,
            views: viewMap)
        mainView.addConstraints(constraints)

    case .Right:
        println("Right")
        constraints = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:[superview]-(<=1)-[innerView]-|",
            options: NSLayoutFormatOptions.AlignAllCenterY,
            metrics: nil,
            views: viewMap)
        mainView.addConstraints(constraints)

    case .CenterX:
        println("Center")

        constraints = NSLayoutConstraint.constraintsWithVisualFormat(
            "V:[superview]-(<=1)-[innerView]",
            options: NSLayoutFormatOptions.AlignAllCenterX,
            metrics: nil,
            views: viewMap)
        mainView.addConstraints(constraints)

        constraints = NSLayoutConstraint.constraintsWithVisualFormat(
            "H:[superview]-(<=1)-[innerView]",
            options: NSLayoutFormatOptions.AlignAllCenterY,
            metrics: nil,
            views: viewMap)
        mainView.addConstraints(constraints)

    default:
        fatalError("Invalid layout")

    }
}

AlignRightCenter工作正常,但Alignleft不工作。
另外,由于垂直居中对所有的情况都是常见的,所以可以将其从开关箱中取出吗?

最佳答案

几个问题:
通常不会在VFL中显式列出superview。而是使用垂直线(|)字符。这:

H:[superview]-(<=1)-[innerView]

并不意味着innerView的前缘在“superview”的前缘之后小于1点。这意味着innerView的前缘在superview的后缘之后小于1点,这可能会使innerView超出其superview的界限,从而导致其被剪裁。
如果这些是您添加的唯一影响innerView的约束,那么您的布局是不明确的。一个不等式允许任何一个可能的值,并且系统没有可靠的方法来选择其中一个值。
你不能在VFL中真正表达中心。您可以将对齐标志传递给constraintsWithVisualFormat(_:options:metrics:views:)(如您所知),但a)这实际上不是可视格式语言的一部分;b)如果不在另一个方向上创建一些虚假的、不需要的约束,则无法执行此操作。也就是说,除非同时创建一些虚假的水平约束,否则不能使用对齐标志垂直居中。(反之亦然)这是因为对齐标志只应用于VFL字符串中列出的视图,而VFL字符串总是包含约束。
你为什么坚持使用VFL?如果使用init(item:attribute:relatedBy:toItem:attribute:multiplier:constant:),则可以简单地传递方法接收的layout参数。对于多个病例不需要switch。你只要:
var constraint = NSLayoutConstraint(item: innerView,
                               attribute: layout,
                               relatedBy: .Equal,
                                  toItem: mainView,
                               attribute: layout
                              multiplier: 1,
                                constant: 0)
mainView.addConstraint(constraint)
constraint = NSLayoutConstraint(item: innerView,
                           attribute: .CenterY,
                           relatedBy: .Equal,
                              toItem: mainView,
                           attribute: .CenterY
                          multiplier: 1,
                            constant: 0)
mainView.addConstraint(constraint)

这将处理所有三个案件。

10-07 19:13