Autolayout Programatic Sizing Woes: Cannot Resize

2019-03-06 08:48发布

If I define my constraints in IB, I can still resize the window that houses the subview.

enter image description here


enter image description here

All the other constraints are the same, but to left, right, and bottom.


When I try to do this in code, I can no longer resize the superview (NSWindow) by hand at runtime, nor maximize it:

class ViewController: NSViewController {

    @IBOutlet var box : NSBox!

    func matchAttribute(attribute: NSLayoutAttribute, view: NSView, superview: NSView) {
        var constraint = NSLayoutConstraint(item: view, attribute: attribute, relatedBy: NSLayoutRelation.Equal, toItem: superview, attribute: attribute, multiplier: 1, constant: 0)
        constraint.priority = 1000
        superview.addConstraint(constraint)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        self.matchAttribute(NSLayoutAttribute.Top, view: self.box, superview: self.box.superview!)
        self.matchAttribute(NSLayoutAttribute.Trailing, view: self.box, superview: self.box.superview!)
        self.matchAttribute(NSLayoutAttribute.Leading, view: self.box, superview: self.box.superview!)
        self.matchAttribute(NSLayoutAttribute.Bottom, view: self.box, superview: self.box.superview!)
    }
}

What must I do to get the same Autolayout behavior programmatically?

1条回答
何必那么认真
2楼-- · 2019-03-06 09:34

Because you aren't adding any constraints to your box in Interface Builder, at the point it loads it is considered to have an ambiguous layout. To remove this ambiguity, Cocoa automatically adds some constraints:

override func viewDidLoad() {
    super.viewDidLoad()

    println(view.constraints)
    //-> <NSIBPrototypingLayoutConstraint:0x600000082e40 'IB auto generated at build time for view with fixed frame' H:|-(0)-[NSBox:0x100716940'This Is A Box'](LTR)   (Names: '|':AutoStack.PPView:0x100516120 )>
    //-> <NSIBPrototypingLayoutConstraint:0x600000082ee0 'IB auto generated at build time for view with fixed frame' V:|-(0)-[NSBox:0x100716940'This Is A Box']   (Names: '|':AutoStack.PPView:0x100516120 )>
    //-> <NSIBPrototypingLayoutConstraint:0x600000082f80 'IB auto generated at build time for view with fixed frame' H:[NSBox:0x100716940'This Is A Box'(480)]>
    //-> <NSIBPrototypingLayoutConstraint:0x600000083020 'IB auto generated at build time for view with fixed frame' V:[NSBox:0x100716940'This Is A Box'(270)]>
}

You'll note that the combined effect of the last two constraints is to fix the width and height of the box - this is why you cannot resize the window, because doing so would violate these constraints.

To get the effect you want, you first need to remove these auto-generated constraints:

override func viewDidLoad() {
    super.viewDidLoad()

    view.removeConstraints(view.constraints)
    // Forbid Cocoa from automatically adding its own constraints to this view 
    view.translatesAutoresizingMaskIntoConstraints = false

    // Note that in your implementation you are needlessly typing <self>
    matchAttribute(NSLayoutAttribute.Top, view: box, superview: box.superview!)
    matchAttribute(NSLayoutAttribute.Trailing, view: box, superview: box.superview!)
    matchAttribute(NSLayoutAttribute.Leading, view: box, superview: box.superview!)
    matchAttribute(NSLayoutAttribute.Bottom, view: box, superview: box.superview!)
}
查看更多
登录 后发表回答