Why does this simple autolayout collapse in IB? - macos

I have a window with a textview in a scrollview and two buttons. I have added constraints at all sides, leading, trailing, top, and bottom. For the buttons I have fixed width and height, and distance to bottom and edge.
I want it to look something like this:
And this is what Interface Builder keeps giving me:
It also keeps offering to fix ambiguities by adding missing constraints, but actually clicking the button has no effect. No constraints are added. The error (and the offer to fix it) remains.
I've tried added the constraints it is asking for, although I can't see why they would be needed and at least the buttons already have (fixed) width constraints. But I keep getting errors and the window keeps getting shrunk to nothing.
When actually running the program, the window looks fine. But I suspect these autolayout errors have something to do with this problem: NSTextView in magnified NSScrollView breaks on resize
The project is here: https://github.com/angstsmurf/spatterlight/tree/helpviewtest
(The branch helpviewtest is a cut down test case created specifically for this problem.)

You have a Text view embedded in a Clip view embedded in a Scroll view, none of which have an intrinsic content size.
IB has no idea what's going to go on at run-time.
So, while everything looks great when you run this, your code will have supplied enough information to lay things out as desired.
To get it to "look right" in IB (and avoid the errors/warnings), you can give the ScrollView a Placeholder Intrinsic Content Size:

Related

Why doesn't my NSWindow resize when I change auto layout constraints?

I think I have arrived at a decent understanding of how auto layout works in Interface Builder (ha). I've got a .xib that says "No auto layout issues". Here's two screenshots of it, with nothing selected and with things selected so you can get a sense of the constraints at work:
Now I would like to, e.g., decrease the vertical spacing between the "Total thumbnail size:" label and the "Use TIFF" radio button matrix. So I click on things to get that constraint selected, and I edit the "Constant" value of it to change it from 47 to, say, 30. When I do so, I expect that the window will shrink vertically by 17, so that all constraints continue to be obeyed. Instead, it shifts the vertical position of the "Size & format" label, breaking its vertical constraints in so doing, and then complains about "Content priority ambiguities" involving a bunch of items; here are screenshots of that state, showing the priority ambiguities:
It wants me to change vertical compression resistance priorities and/or vertical hugging priorities to allow it to compress/expand something away from its intrinsic size; but I don't want to do that. I want all of those items to retain their intrinsic size, and I want the window to resize. I can resize the window manually, by -17, and move the various items into their proper positions, and then it says "No auto layout issues" again; so there is really nothing difficult or ambiguous about this situation except that for some reason it refuses to resize the window as it ought to. So, my question is: how do I avoid it doing this, and have it just resize the window and move things properly on its own? I don't understand why it's so confused; it seems to me that there is a clear, unambiguous chain of vertical constraints from the top to the bottom of the window, and changing one of those constraints ought to simply force the window to resize. I've tried using "Update Frames" but it doesn't seem to help.
I think I have uploaded the .xib file, prior to the constraint change, to my Dropbox here: https://www.dropbox.com/s/vp90s1fh692i8pi/CopyThumbs.xib.
I grabbed your xib and played around with a few things... I can only find two items that would be causing problems.
But first, a couple tips (based on my experiences):
Start by making your window larger than you'll need
with your layout, make it maybe 600 x 600
As you add UI elements add only Vertical and Leading constraints (we can center the Cancel/Copy buttons later
of course, I also mean Horizontal inter-element constraints
For wrapping multi-line labels (i.e. your "Choose how you want..." label), give it a specific Width constraint
285 is a good value for your layout... you can adjust this later as desired
Don't give a Bottom constraint yet
Your xib now looks like this (I left your Cancel button Leading as you had it >= 50):
Now you can tweak your vertical spacing constraints, without worrying about the window frame sizing.
Once you're happy with the layout, you only need one Trailing constraint (on your multi-line label) and one Bottom constraint (on the Cancel button).
Add those constraints, and your window frame should resize itself. If it doesn't, selecting "Update Frames" should fix it.
The two problem items that I mentioned... you have Content Hugging Priority on both "Matte thumbnails..." and "Frame thumbs..." set to 250. Those should both be at their default of 750.
Your Cancel/Copy buttons should horizontally center themselves, with your current constraints. I'd suggest, though, putting them in a StackView, and then constraining that StackView Top to the element above it, and Bottom to the Superview... and thenHorizontally Centered.
Edit
Note: I don't work for Apple... these comments are simply my anecdotal observations.
First, Interface Builder is (as we all know) not the same as run-time output. It's close, but it's certainly not identical.
Second, IB makes a lot of assumptions -- while at the same time, it has no idea what we're going to do next.
A perfect example from iOS development:
If, in IB, I add a UIScrollView to a view without adding any content to it, IB will endlessly complain about Content Size Ambiguity... and won't even position the view to reflect the constraints.
That's because IB doesn't know that I'm going to add subviews (with proper constraints) at run-time. And the only way to get rid of the Red "Error" messages is to add a subview in IB which I would then have to immediately remove at run-time (ugh).
IB also tends to complain / warn about "Fixed width constraints may cause clipping" and, as you're experiencing, "Localization Issue: Trailing constraint is missing."
It doesn't matter if my label is static (text will never change) or if I have the constraints set exactly how I want them. IB is going to try its darnedest to convince me that I need to change things.
This is one of the reasons many people move away from using Storyboards / XIBs. For my job, we don't use any XIBs, and the only Storyboard we use is for the LaunchScreen (iOS).
I might lay things out in IB to start, and to get a good idea of how I want my layout to look, but then I write it all in code for the end result.
Not that I'm saying this approach is better... plenty of times when I think to myself "Hey, I can drag/drop UI elements, add constraints and IBOutlet / IBAction connections, and I'd be done already!"
Again, though, just my personal thoughts on the topic.

Seeking a simple Mac OS NSTextView example using AutoLayout

After much reading and experimenting, I still cannot get a simple TextView to resize fully in the horizontal direction using Xcode 5.0.2 in Mavericks. It resizes partially as the window is resized, then stops with long lines wrapped around even though my containing NSScrollView continues to resize as expected (it has four default constraints and no horizontal scroller).
Can anyone point me to a simple code/IB+AutoLayout example, preferably just a window containing just an NSTextView dragged in from the IB template library --- one that works? The Apple TextEdit sample code is almost irrelevant for this purpose although it does resize horizontally quite well. Also, there is the clip view for which I can find little information.
Any other tips appreciated.
Thanks.
Answering my own question:
Turns out that my problem had nothing to do with AutoLayout and little to do with NSTextView. It was the textfile I was using to test my code! This file was composed of records with tab-delimited fields.
Turns out that NSTextView comes with a default NSParagraphStyle with predefined tab stops that end at character 56 whereas my test file had tabs beyond that. Therefore, my lines wrapped around at the last defined tab no matter how much I stretched the window.
After changing my search terms, I found what I needed at the following links:
Premature line wrapping in NSTextView when tabs are used
How to have unlimited tab stops in a NSTextView with disabled text wrap
Apologies for wasting bandwidth.
Not sure why such a simple thing does not work in your case, but nevertheless here's what I did in Xcode to get an NSTextView follow window resize:
Create a new project (not document based in my case but it doesn't really make a difference)
Drag a NSTextView from the palette to your window. Align all four edges with the window edges.
Open the "Add constraints" pop-up (second button from the segmented control on the bottom-right part of your IB view.
Each of the four spacing constraints should show a number equal to the distance of your text view from the container window. If you aligned them, this number should be either 0 or -1. Click the down arrow for each of them and select "Use Current Canvas Value". Do it for all four. Make sure no other constraints are selected.
Click on "Add constraints" on the bottom of the panel.
Run your project. Your textview should resize with the window.
Also, as Jay's comment mentions, make sure you do not have any "leftover" constraints in your view. You can check this either by observing Xcode's warnings, or manually by inspecting your view's constraints by going to the Size Inspector tab (4th tab on the Utilities bar).
If you need to have your textview arranged in a more complex layout, it might be worth taking a look at the AutoLayout Guide.

Subview that expands with window using NSAutolayout

I'm trying to learn auto layout so I can set up a moderately complicated display the way I want. I'm starting with a simple version. At least I thought it was simple.
I have a content view containing a NSScrollView, and a zoom slider. The scroll view is, of course, just a window into a larger 'canvas' on which the user can do things.
I'd like the scroll view to be as big as the window allows, with the slider underneath.
I've tried many things none of which work, in some cases when I resize the window smaller, the scroll view goes on up over the window's top bar, obscuring the title and the red yellow, green, dots.. this is just a grumble, I won't attempt to describe how I got it.
I'm working with Visual Format Language.
The immediate problem: I can only get the thing to work at all if I put in a hard size constraint on the scroll view.
I've got constraints like #"V:|[ScrollView]-[ZoomSlider(==35)]-| and
#"|-20#1000-[ScrollView]-|"
With these, nothing shows at all, until I put a hard size on the scroll view:
For example, #"V:[ScrollView(>=70#20)]" and #"[ScrollView(>=140#20)]" results in a little tiny scroll view (as expected) just above the slider.
Window is resizable, all right.
Is there a simple way to make the scroll view resize to occupy the most space possible when I resize the window? The only way I can think of off hand is to produce metrics for the scroll view based on window size, and use a notification to change the constraints when the window size changes. There should be something simpler!
THanks.ee
OOps. Thought I knew the answer until I started to write it.
AT least here is a partial explanation of things that were causing me problems.
You can't add constraints that position or size the Window's content view. But apparently you can mess them up by deleting them programatically. Some of my problems were solved by getting rid of
[self.myContentView setTranslatesAutoresizingMaskIntoConstraints:NO];
and
[self.myContentView removeConstraints:self.myContentView.constraints];
This left me with a lot of conflicting constraints. I fixed this be eliminating all content window constraints that I could in IB, then by marking the rest as placeholders.
I've got a ways to go before I understand how to use auto layout, but doing it in code is easier (for me) than doing it with IB

Problems with NSTabView autolayout (view based NSTableViews inside tabs)

I have an NSTabView which has 5 tabs. Each tab contains an NSTableView (which, as default, is nested in NSScrollView). This is all loaded from a xib file with autolayout turned on. I'd like each table to fully occupy it's respective tab. Using autolayout I select each tab and carefully setup the NSScrollView so that it snaps its top, bottom, lead, and trailing edges to superview. After I do this for the 5 tabs, I'll resize the xib to give it a test. When I cycle back through the tabs, some stay snapped to the superview and some do not. There appears to be some sort of order to this but it is beyond what I can explain.
What's really frustrating is that sometime this will run okay, and sometimes it will crash because of unsatifyable constraints. For now I am using springs/struts but I like autolayout and would like to get it working.
I am afraid that it is the nesting of the tables inside scroll views which is causing the issues.
If you lay this out your own nib, you should be able to reproduce it.
I am hopeful that this can be solved by adding NSLayoutConstraints at runtime, if OSX is anything like iOS's autolayout. Using IB you cannot assing constraints to anythign other than super and sibling (no cousins). This can be done at runtime.
I am hoping someone out there has encountered this issue and has a solution.
Why do the constraints in the layout show a fixed constant instead of auto? Could that be it?
You mentioned cousin constraints, I believe you can add in the in IB if you select two views in the document outline on the left hand side and then add a constraint. I'm unable to pick any two views in IB if I'm using the main window but I can do it in the document outline.
Lastly, you mention it will run okay sometimes but not others - and if that's the case it sounds like something else is adding constraints. Instruments should have a template for tracing constraints, if you can reproduce it you may get a clue to what is introducing the incompatible constraint.

Put a view in the bottom of another view with a fixed size

Sorry folks if my question seems to be trivial, but xcode drives me crazy.
I don't want anything else, just put a view in the bottom of a view controller in XCode by IB, that has FIXED height even if I rotate device. It stay simply in the bottom and its size stays unchanged.
Autolayout constraints changes its size all the time, hides if I rotate etc. I could not find the settings for this simple problem.
I need this (with fixed size, that does not change/hide when rotating):
How can I do that?
Have you tried unchecking autolayout and playing around with autosizing. Try the below setting . It should work.

Resources