Views not displaying correctly after adding them to NSStackView programmatically

2.3k views Asked by At

I'm trying to add some views (NSTextField in this example) to NSStackView:

I've added NSStackView instance into XIB file, linked it to outlet as widgets into Document. In ...didLoadNib I'm doing this:

NSTextField *tf = [[NSTextField alloc] init];
tf.stringValue = @"124";
[tf setFrameSize:NSMakeSize(100, 20)];
[widgets addView:tf inGravity:NSStackViewGravityLeading];
NSLog(@"%f - %d", NSHeight(tf.frame), [tf hasAmbiguousLayout]);

NSTextField *tf2 = [[NSTextField alloc] init];
tf2.stringValue = @"123";
[tf2 setFrameSize:NSMakeSize(100, 20)];
[widgets addView:tf2 inGravity:NSStackViewGravityLeading];
NSLog(@"%f - %d", NSHeight(tf2.frame), [tf2 hasAmbiguousLayout]);

TextFields are placed into StackView, but they're placed into same position, i.e. the second overlaps first completely. I still can select first by [space+tab].

Here's console output:

2015-06-13 17:11:00.736 celty-test[62306:9217679] 20.000000 - 1
2015-06-13 17:11:00.739 celty-test[62306:9217679] Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x608000084bf0 V:[NSStackViewSpacer:0x6080001834d0(>=8)]>",
    "<NSLayoutConstraint:0x608000084f10 V:[NSTextField:0x608000183330]-(0)-[NSStackViewSpacer:0x6080001834d0]>",
    "<NSLayoutConstraint:0x608000085460 V:[NSStackViewSpacer:0x6080001834d0]-(0)-[NSTextField:0x608000183400]>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084970 h=--& v=--& V:[NSTextField:0x608000183330]-(0)-|   (Names: '|':NSStackViewContainer:0x6000001a0700 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084d30 h=--& v=--& V:[NSTextField:0x608000183400]-(0)-|   (Names: '|':NSStackViewContainer:0x6000001a0700 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084d80 h=--& v=--& V:[NSTextField:0x608000183400(20)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x608000084bf0 V:[NSStackViewSpacer:0x6080001834d0(>=8)]>

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.
2015-06-13 17:11:00.802 celty-test[62306:9217679] Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x608000084f10 V:[NSTextField:0x608000183330]-(0)-[NSStackViewSpacer:0x6080001834d0]>",
    "<NSLayoutConstraint:0x608000085460 V:[NSStackViewSpacer:0x6080001834d0]-(0)-[NSTextField:0x608000183400]>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084970 h=--& v=--& V:[NSTextField:0x608000183330]-(0)-|   (Names: '|':NSStackViewContainer:0x6000001a0700 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084d30 h=--& v=--& V:[NSTextField:0x608000183400]-(0)-|   (Names: '|':NSStackViewContainer:0x6000001a0700 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000084d80 h=--& v=--& V:[NSTextField:0x608000183400(20)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x608000085460 V:[NSStackViewSpacer:0x6080001834d0]-(0)-[NSTextField:0x608000183400]>

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.
2015-06-13 17:11:00.814 celty-test[62306:9217679] 20.000000 - 0

XIB and result screenshots: XIB

result

There's no constraints added to StackView. StackView should be vertical. There will be dynamic amount of textfields added to stackview.

1

There are 1 answers

4
Ken Thomases On BEST ANSWER

You need to set the translatesAutoresizingMaskIntoConstraints property of the text fields to false.

Normally, you shouldn't do this if the view is being placed by some other code. That is, you would expect the stack view to decide whether that property should be on or off because it's in control of placing it into the view hierarchy. However, there's a bug in NSStackView with regards to this up through 10.10, so you have to turn that off yourself.

The clue is that the set of unsatisfiable constrains include ones of type NSAutoresizingMaskLayoutConstraint.