如何在addSubview之后添加约束,以便使用superview

时间:2015-07-04 20:40:47

标签: xcode macos swift cocoa autolayout

我有一个展示此问题的示例项目

https://github.com/ericgorr/autolayout_with_addsubview.git

我有一个名为CalcView的视图,我想以编程方式将其作为子视图添加到应用程序主窗口的视图中。当我调整窗口大小时,我想要调整CalcView的大小

在MainWindowController的windowDidLoad中,我通过执行以下操作添加子视图:

let calcViewController  = ELIZCalcView()
let calcView            = calcViewController.view

calcContentView?.addSubview( calcViewController.view )

我尝试通过执行以下操作来添加约束:

let bindings            = [ "calcView": calcView ]

let horizontalContraint:[AnyObject] = NSLayoutConstraint.constraintsWithVisualFormat( "H:|[calcView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: bindings )
let verticalContraint:[AnyObject]   = NSLayoutConstraint.constraintsWithVisualFormat( "V:|[calcView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: bindings )

calcContentView?.addConstraints( horizontalContraint )
calcContentView?.addConstraints( verticalContraint )

现在,对于知道如何正确解释该代码的人来说,很明显它不会起作用。在我运行我的应用程序后,我根本无法调整窗口大小。此外,我在控制台中看到以下错误消息:

2015-07-04 16:04:45.019 aocsCalc[5797:3526462] Unable to simultaneously satisfy constraints: (
    "<NSLayoutConstraint:0x618000082440 V:|-(0)-[NSView:0x600000120f00]   (Names: '|':aocsCalc.ELIZHighlightView:0x608000120500 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x618000084100 h=--& v=&-- V:|-(-2)-[NSView:0x600000120f00]   (Names: '|':aocsCalc.ELIZHighlightView:0x608000120500 )>" )

Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x618000082440 V:|-(0)-[NSView:0x600000120f00]   (Names: '|':aocsCalc.ELIZHighlightView:0x608000120500 )>

Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens.  And/or, break on objc_exception_throw to catch this in the debugger.

如果删除垂直约束,则错误消息消失,我可以垂直调整窗口大小。

那么,我需要做什么简单的事情,因此CalcView会随窗口一起调整大小?

1 个答案:

答案 0 :(得分:15)

在将calcView添加为子视图之前,请尝试插入以下代码行:

calcView.translatesAutoresizingMaskIntoConstraints = false

这可以解决您的问题。

默认情况下,在UIView / NSView上,此属性设置为YES / true,并根据自动调整掩码创建自己的约束集。这些自动制约的约束与您在代码中创建的约束相冲突。

在错误描述中也清楚地说明了这一点。在第2行和第3行,它向您显示有关于一个视图的两组垂直约束 - NSView:0x600000120f00,它似乎是您的calcView。

<NSLayoutConstraint:0x618000082440 V:|-(0)-[NSView:0x600000120f00] 
<NSAutoresizingMaskLayoutConstraint:0x618000084100 h=--& v=&-- V:|-(-2)-[NSView:0x600000120f00]

它们都是垂直的。首先想要查看超级视图的顶部没有边距。第二个(自动创建)想要以较小的余量捕捉它,大概取自它在Interface Builder中的布局。

<强>更新

创建一个新的Cocoa Application项目并粘贴以下代码:

override func viewDidLoad() {
    super.viewDidLoad()

    let view = NSView()
    view.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(view)

    //Making it red just to see a little better. Ignore this two lines.
    view.wantsLayer = true
    view.layer?.backgroundColor = CGColorCreateGenericRGB(1, 0, 0, 1)
    //-----------------------------------------------------------------

    let views = ["view" : view]
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|-[view]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: views))
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[view]-|", options: nil, metrics: nil, views: views))

}

新创建的NSView被捕捉到具有标准边距的视图控制器主视图(8个点,在可视格式字符串中描述为“ - ”)并且正在使用主视图调整大小(参见图片)。一点点提示 - 您不必以可视格式指定“H:”,只需“V:”。它默认是水平的。

这可以让您更好地了解如何以编程方式添加约束。代码可能不是最佳的,我在Obj-C中编码并且知道很少的Swift。

我已经下载了你的项目。错误可能位于复杂的视图层次结构和xib操作中。但这是另一个故事。还要小心滚动视图,它们在autolayout方面有点棘手,你可以在SO上找到很多关于它的报道。快乐的编码:)

enter image description here enter image description here