Using contentLayoutGuide for constraints
In Yosemite, constraints now have an 'active' property that you can set to make the constraint active without placing it on a common ancestor. I think it was created specifically for cases like this where you don't know the common ancestor.
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem: myView attribute: NSLayoutAttributeTop relatedBy: NSLayoutRelationEqual toItem: window.contentLayoutGuide attribute: NSLayoutAttributeTop];
constraint.active = YES
I came across this problem recently and thought i would share the recommended way of handling this today. The technique can be seen in the WWDC 2016 Session 239 "Crafting Modern Cocoa Apps". There have been changes in the API, since they released it, so there is a twist.
Following code puts an NSSearchField, named searchField
, right below the title/tool-bar area by constraining it to the top of the content view using the windows contentLayoutGuide. The following code is added to an NSViewController.
@IBOutlet weak var searchField: NSSearchField!
private var titleBarConstraint: NSLayoutConstraint?
override func updateViewConstraints() {
if titleBarConstraint == nil {
if let topAnchor = (searchField.window?.contentLayoutGuide as? NSLayoutGuide)?.topAnchor {
titleBarConstraint = searchField.topAnchor.constraint(equalTo: topAnchor, constant: 8)
titleBarConstraint?.isActive = true
}
}
super.updateViewConstraints()
}
In Interface Builder the NSSearchField is positioned, using autolayout, to match the look during runtime. Click on the top constraint of the NSSearchField and enable the "Placeholder Remove at build time" checkbox.
The contentLayoutGuide still returns Any?
but it is an NSLayoutGuide. That was the twist.