2

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
ShadowPrince
  • 127
  • 1
  • 1
  • 8
  • Are there constraints on Widgets? You have the gravity setting both text fields to the bottom of the widget, and it looks from your debugger like you have a spacing added between the text fields, but they need to be pinned to the top-bottom of the widget if you want a resizable widget. Like `"V:|[tf]-8-[tf2]|"` – Tim Jun 13 '15 at 14:35
  • There's no constraints I've added either to ScrollView or textfields. – ShadowPrince Jun 13 '15 at 15:03

1 Answers1

8

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.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Thank you kindly. Only second day into Cocoa and already revealing a bug. – ShadowPrince Jun 13 '15 at 16:40
  • It looks like this is fixed on 10.11, with `NSStackView` setting `translatesAutoresizingMaskIntoConstraints` for the added views to false. – Taylor Jun 15 '15 at 20:31
  • Thank you so much! I've just spent hours trying to get this to work and this fixed it. Oddly enough I have another stack view with the same set up and it works fine without doing this... – DanielGibbs Jun 24 '15 at 22:12
  • Non-top-level views in a NIB/storyboard which uses auto layout have `translatesAutoresizingMaskIntoConstraints` turned off by IB. It's mostly views that are created programmatically that have the problem, although it can also be top-level views from a NIB/storyboard, or ones from a NIB/storyboard that's not set to use auto layout. – Ken Thomases Jun 24 '15 at 22:24