Skip to content

Instantly share code, notes, and snippets.

@helje5
Created November 27, 2018 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helje5/0456aafe2a27b4ed37ce08bb7a53f133 to your computer and use it in GitHub Desktop.
Save helje5/0456aafe2a27b4ed37ce08bb7a53f133 to your computer and use it in GitHub Desktop.
Nested NSStackViews lead to ambiguous layout
import Cocoa
final class TestView : NSView {
static func makeAndAttachToView(_ rootView: NSView) {
let view = TestView()
view.translatesAutoresizingMaskIntoConstraints = false
rootView.addSubview(view)
NSLayoutConstraint.activate([
view.leadingAnchor .constraint(equalTo: rootView.leadingAnchor),
view.trailingAnchor.constraint(equalTo: rootView.trailingAnchor),
view.topAnchor .constraint(equalTo: rootView.topAnchor),
view.bottomAnchor .constraint(equalTo: rootView.bottomAnchor)
])
}
override init(frame: NSRect) {
super.init(frame: frame)
NSLayoutConstraint.activate([
widthAnchor .constraint(equalToConstant: 320),
heightAnchor.constraint(equalToConstant: 200)
])
func makeStackView(_ orientation : NSUserInterfaceLayoutOrientation,
_ alignment : NSLayoutConstraint.Attribute,
_ view : NSView)
-> NSStackView
{
// The subclasses are just for debugging in the Xcode View Debugger
let v = NSStackView(views: [view])
v.translatesAutoresizingMaskIntoConstraints = false
v.orientation = orientation
v.alignment = alignment
v.spacing = 2.0
return v
}
let searchField = NSSearchField(frame: NSMakeRect(0, 0, 128, 128))
#if false // not ambiguous
let view = makeStackView(.horizontal, .centerY, searchField)
#else // ambiguous
let view = makeStackView(.horizontal, .centerY,
makeStackView(.vertical, .width, // .leading
searchField)
)
#endif
addSubview(view)
NSLayoutConstraint.activate([
view.leadingAnchor .constraint(equalTo: self.leadingAnchor),
view.trailingAnchor.constraint(equalTo: self.trailingAnchor),
view.topAnchor .constraint(equalTo: self.topAnchor),
view.bottomAnchor .constraint(equalTo: self.bottomAnchor)
])
}
required init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@helje5
Copy link
Author

helje5 commented Nov 27, 2018

This removes the ambiguity:

      let innerStack =  makeStackView(.vertical, .width, // .leading
                                      searchField)
      innerStack.setHuggingPriority(.defaultHigh, for: .vertical) // <=
    
      let view = makeStackView(.horizontal, .centerY, innerStack)

Note: it really is the NSStackView specific setHuggingPriority(_:for:), not setContentHuggingPriority(_:for:), which still results in the ambiguity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment