Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using contentLayoutGuide for constraints

I´m trying to use a NSTextView with the new Vibrant theme in OSX 10.10 after watching the session from WWDC on advanced features of the new UI. My text view is not placed adjacent to the titlebar so I have made the content view fully sized so I can place the text view beneath title bar.

My problem is that I have a NSView between the text view and title bar which should be placed directly beneath the title bar but I can not get auto layout to do this for me. In the video they're giving this sample code using the new contentLayoutGuide property in NSWindow:

NSLayoutConstraint *topEdgeConstraint = [NSLayoutConstraint constraintWithItem:myView attribute: NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:window.contentLayoutGuide attribute:NSLayoutAttributeTop];

However I can not get this to work, whenever I try to install the constraint Xcode gives me

Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal.

I get that the window property used in the example is not in the subtree of the view since the view is placed inside the window but how am I supposed to access the contentLayoutGuide property?

Currently I´m trying to add the constraint in the -awakeFromNib method in a subclassed NSWindow. Wrong approach maybe?

Thanks in advance

like image 887
Hampus Avatar asked Feb 11 '15 23:02

Hampus


2 Answers

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
like image 113
sam Avatar answered Nov 04 '22 07:11

sam


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.

like image 7
TimTwoToes Avatar answered Nov 04 '22 06:11

TimTwoToes