【问题标题】:How to add constraints after an addSubview so the subview resizes with the superview如何在 addSubview 之后添加约束,以便子视图与父视图一起调整大小
【发布时间】:2015-09-22 08:47:48
【问题描述】:

我有一个示例项目来演示这里的问题

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 与窗口一起调整大小?

【问题讨论】:

    标签: xcode macos swift cocoa autolayout


    【解决方案1】:

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

    calcView.translatesAutoresizingMaskIntoConstraints = false
    

    这应该可以解决您的问题。

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

    错误描述中也清楚地说明了这一点。在第 2 行和第 3 行,它向您展示了关于一个视图的 2 组垂直约束 - 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 操作中。但那是另一回事了。还要小心滚动视图,它们在自动布局方面有点棘手,你可以在 SO 上找到很多关于它的报道。快乐编码:)

    【讨论】:

    • 我在 OS X 开发方面没有太多经验,但我认为 UIView 和 NSView 在约束方面表现相同。 Docs 说 NSView 具有该属性。你一定是打错字了。
    • 将它从函数调用更改为属性赋值消除了编译错误,但我看到的实际行为要糟糕得多。视图根本不再正确定位在窗口上。我已经用更改更新了 git hub 项目。
    • 您的原始问题已得到解答,因此您应该考虑将功劳归功于 NKorotkov。我已经下载并运行了您更新的项目,但看不出问题出在哪里。您应该明确说明您想要实现但不能实现的目标 - 可能在一个单独的问题中(顺便发布示例项目 +1)。
    • @ericgorr 我已经更新了我的答案。这应该足以理解如何在代码中使用自动布局。
    • 谢谢。但是,我正在为我在 github 上提供的代码寻找解决方案。
    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多