cocoa: weird purple constraint for split view - cocoa

If I add three split views as following image, the third split view, referred as splitView-3, will automatically generate a constraint for custom view in that split view, like Height(42) of customview1. As a result, I can't change the height of customview1 in Interface Builder.
why does Interface Builder automatically generate a purple constraint, like Height(43), for customview1?
Any help would be appreciated.

It generates it because you manually sized the view to a specific height in its superview. Promote the constraint (in the size Utility Panel) to a user constraint and delete it. That should get you most if not all the way there (but I can't tell without seeing the rest of your constraint configuration).

Joshua is right... but there is one little tidbit I think needs to be explained.
Xcode needs constraints to determine position and size of ALL items. The purple ones it sticks in because there aren't enough constraints to satisfy those needs without sticking in a few extra.
So, Xcode is sticking in a constraint for height, that means it has no way to determine the height from your existing constraints. You can define it by adding constraint so:
the height is equal to the height of some other item
by setting the bottom distance X points away from another item
by setting the bottom position relative to it's superview
or .... well, a lot more, but hopefully you get the idea
Once you add in a constraint which let's Xcode know the view's height, that purple one will either vanish or become blue so you can delete it and have it not come back.

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.

How can I have a Label in a UIStackView and allow clipping? [duplicate]

I downloaded the new Xcode and in Interface Builder I'm having a ton of problems with warnings that say things like:
Fixed Width Constraints May Cause Clipping
It looks like this:
I do have localization for several languages and I understand the warning that in another language a label's size may change, but my app doesn't have this problem. I ran and tested it in Xcode 8 yesterday, it was fine. I don't want to spend hours and hours adding pointless new constraints.
Any suggested solutions?
I was getting the same warnings even without multiple languages in my app, which led me to find out what was really going on. . .
There are a few different things going on here. I was able to silence the fixed-width warnings in my own app by changing the width of the object spacings from fixed width to greater than or equal or less than or equal.
This can be done by selecting the object in interface builder, going to the size inspector and changing it there:
Or, select the constraint from the document outline, go to size inspector, and change it there:
As far as the warning at the top of your screenshot:
Fixed leading and trailing constraints with a center constraint may
cause clipping
Here is a screenshot from my own app in which I was getting the exact same warning:
I had the label with the # sign set to leading and trailing to the buttons but also to align the center with the rating label. Once I removed the center alignment constraint, the warning disappeared, but I was left with an improperly laid out set of objects.
It is then that I resigned myself to embrace the Stack View. As annoying as it is to use, when you get all of the constraints and settings right, it lays out beautifully and with no warnings.
Edit
As Repose writes in the comments, sometimes simply adding >= 0 will be what you need, as you are making sure two elements do not overlap.
You can try Disabling "Respect Language Direction" on per Constraint basis to silence the warning and see if it helps. Select your constraint and open Attributes/Size Inspector. Please see image attached.
If you are not planning on localizing your app to other languages, then this solution should not have any drawbacks. For localized apps you have to be more conscious of your label and font sizes.
p.s. This solution works for iOS. For macOS try >= or <= to silence the warning.
p.p.s. Labels in the picture below are much easier to create using AutoLayout and attributedString property on a single UILabel or UITextView using NSMutableAttributedString. The image is for demonstration purposes only.
For labels and buttons which are localized this warning makes sense and you should provide the necessary constraints so your labels don't overlap. If they don't overlap now they might in the future, so it won't hurt to provide the constraints.
Xcode helps you add these constraints automatically:
In the document outline of your storyboard click on the yellow arrow and either choose "fixed leading" or "fixed trailing", depending on where the text is on your screen (left or right). This will fix it for most issues.
If you have this issue with a Button without any text (only image), try to remove the "default title" which might still be set for the button:
With Labels, you can set Lines is 0 and Autoshrink properties is Minimum Font Size to remove Fixed Width Constraints May Cause Clipping warnings, like this:
Another quick solution !
For a UIButton by changing the title from plain to Attributed text also resolved my issue:-
I know this question has already been answered but what I did to fix this error in my case was to add the "Aspect ratio" property and then eliminate the width or height constraint this worked pretty well and was less effort, and I managed to keep the same output and adapt my view for the different devices.
Swift 4 , Xcode 9.1 :
About this issue, I think your object don't know what it's the correct center position in the context of it's superview, and using remove, greater than or other leading/trealing settings most of times don't work correctly. First, you must check the correct constraints of your superview.
If your superview/s are correctly setted, you can try to "explain" to your object what is the correct position in the view by setting the "horizontally in Container" constraint:
If you need fixed width constraint for button just set width constraint priority to 700.
I had the same problem, but when I changing to >= it automatically set the constant to 0, if I choose 60 for instance, the warning appears again. So I was in a loop with the problem.
I could fix embedding my Label in a View
Editor > Embed In > View
In Label I set Top, Bottom, Leading and Trailing with constant = 0
In View I set the constraints that I was expecting before.
I had the same problem when moving to Xcode 9 and found an approach that's useful for certain kinds of layouts. In my case, I wanted a table header in which two columns (UILabels) were of fixed width and another was of variable width. Regardless of how I specified column widths (including using constraints greater than or equal instead of equal, etc.), I kept getting the warning about possible clipping. In my case, I wanted the variable width column (UILabel) to clip if necessary. I could have just ignored the warning, but don't like doing that.
The approach that worked here was to create a UIView with appropriate size constraints and embed the UILabel as a subview in the UIView. Then truncation happens if necessary and I get no warning. This works whether the UIView/embedded UILabel is in a StackView or not.
This is essentially the same approach as that of Haroldo Gondim but here you can see it also works with or without StackView.
The following image shows the approach, with and without StackView. "SpacerName" is a variable width UIView containing a label and "SpacerPD" is one with a fixed width of 80. [Colors are not significant; just there to show where the views are.]
As you can see in the image below, I was having the error "Fixed Width Constraints May Cause Clipping" because although I had set my textbox to be vertically centered and my label to have a left margin constraint, I hadn't defined a constraint for the text box in relation to the label, so XCode was alerting me that the textbox could clip (be rendered above) the label.
After adding the left constraint to the text box to always stay some distance apart from the label the error was considered solved by XCode and it didn't bothered me with the constraint warning anymore.
I had a similar issue when trying have the button with the same paddings from the edges of the super view.
I've ended up using horizontal center constraint and equal widths constraint to the super view.
To Fix The Error: Fixed Width Constraints May Cause Clipping” and Other Localization
You need to select the view/object, go to the "Show Size Inspector", find the Width Constraint and set the Constant to Greater or Equal to:
To Fix The Error: Leading/Trailing constraint is missing which may cause overlapping with other views
This means that the view/object Xcode is complaining about, is missing a Leading or Trailing Constraint to a neighboring view.
While holding control, drag to a near by view/object
Add a Leading or Trailing Constraint

Cocoa Resizing Two Stacked Tables

I have a view with two vertically stacked Table Views. When I resize the application window, the lower table view expands. This is because I didn't specify a height for it. It has a fixed distance to the bottom of the window and a fixed distance to the table view above it. If I attempt to remove the fixed height for the upper table view, the constraints editor complains. Is it possible to have both table view expand equally when I resize the application? If not, is the possible to allow the upper table view to be resized when the application is running?
I found a way to do this as long as there is some sort of control between the two tables. A label will work fine. Using constaints:
For the control in between the two tables, set the Alignment constraint to "Vertically in Container. This will perfectly center the control. You can offset it above or below center by adding a positive or negative value in the combobox next to the option.
For the top table, pin the top of the box to the top of the window or any other place that fits your design.
Set the bottom constraint to some offset from the control in step 1.
Set the bottom constraint of the bottom table to something fixed like the bottom of the window.
Set the top constraint to some offset from the control in step 1.
Be sure not to set the height of either table.
When the window moves vertically, the control in step 1 will be moved to keep it in the center plus or minus any offset you provided. The two tables will be expanded or contracted accordingly.

NSTableView inside NSOutlineView and NSView-Encapsulated-Layout-Height

I'm building a OS X application using Swift and Xcode 6.4 on OS X 10.10.5.
On a specific view of my application I would like to have a view like this one Xcode has on the Data Model Editor.
I tried to replicate this view using an OutlineView where each "row" would have a title and a TableView plus two buttons (for the plus and minus buttons). For tests purposes I've separated the title for the TableView+Buttons, something like this (this was one of many different attempts).
Everything is working as expected except the View that has the TableView+Buttons, that is never higher than 17 pixels. If I define everything in one view, I have the same problem. I've tried defining the needed constraints but in that case there is a problem with a constraint that seems automatic called NSView-Encapsulated-Layout-Height, that forces the height to 17 pixels:
NSLayoutConstraint:0x61800008ea10 'NSView-Encapsulated-Layout-Height'
> V:[NotesTable(17)] (Names: NotesTable:0x60000012e2e0 )
I'm not defining any constraint to 17 pixels, I've tried testing with some parameters that usually insert automatic constraints (autoresizesSubviews/translatesAutoresizingMaskIntoConstraints/autoresizingMask) but I was only able to translate that 'special' constraint to another format and the grow doesn't get bigger.
Tried to search the web but I only get cases where that Encapsulated constraint makes sense and is useful.
Do you know where or how can I disable that constraint or change its value to the height I need?
Table and outline views on OS X do not support automatically determining the row height from the dynamic height of the cell views. They either have an explicit static row height, a static row height determined by the design-time height of the cell views, or a dynamic row height determined by the delegate and its implementation of -tableView:heightOfRow: or -outlineView:heightOfRowByItem:.
For your case, you're going to have to implement the delegate method. Furthermore, the delegate method can't query the actual cell view because it may not exist and the outline view would need the row height before creating it. So, the delegate has to compute it some other way.
One way is to keep a standalone view hierarchy of a prototypical cell view. When the delegate is asked for the row height, it configures that view hierarchy as it would be for the actual cell view for that row/item, forces it to lay itself out, and then queries its height. Configuring the view hierarchy may be as simple as setting the objectValue of the top-level view (if it's an NSTableCellView, a control, or otherwise implements the setter). But if your delegate does other configuration, such as in its -outlineView:viewForTableColumn:item: method, then you'll need to replicate that for this prototype view hierarchy.
Also, when any factor that would affect a row's height changes, you have to call the outline view's -noteHeightOfRowsWithIndexesChanged: method to let it know that, so it will re-query your ...heightOfRow... method.
Finally, bare table views are not especially amenable to being constrained to sibling views or their superview. They really want to live in scroll views and continue using springs-and-struts to position and size themselves. See my answer to another question for a discussion of this. It is possible that this has been improved in recent versions of the OS. Anyway, you're going to have to observe the table view's frame-change notifications (and ask it to post such notifications) in order to know when it grows. And your ability to set constraints to relate it to any other views in the cell view hierarchy will be severely limited, because it will need translatesAutoresizingMaskIntoConstraints turned on.

How do you use NSScrollView with auto layout?

Ok. I've been at this over and over. I've seen blogs and cocoa dev threads.
I've seen Kyle Sluder's proposed solution, but have yet to find a solution that really works.
How can you position subviews of an NSScrollView with auto layout?
Is it just silently broken ?
Nothing seems to work.
Ok, old question, but this particular issue is a personal bugbear of mine so I'll answer it anyway!
The first thing to note is that an NSScrollView contains an NSClipView, which itself has a view outlet called documentView. These are all added for you when you drag a new scroll view into your storyboard or nib file. By default, the document view is an NSView called simply "View". If you're using a custom view, you can just select this and set its type in the inspector on the right to whatever you want. Otherwise, you'll be adding subviews to it.
The big thing that is easy to miss here is that, by default, the document view has its layout set to 'Translates Mask Into Constraints'. This is fine if the content size will never, ever change, and if that's the case you can simply set the frame of the document view to whatever you want and leave it at that. If you want it to automatically resize itself to fit its content however, there's a few things you'll need to do.
First off, that document view needs to have a completely unambiguous size. If you're using a custom view, I'd recommend giving it an intrinsicContentSize. You should also set 'Intrinsic Size' in IB's inspector to 'Placeholder' and give it a suitable value, or you'll get a bunch of autolayout warnings. If your document view gets its size from its content, all of the subviews must be linked in an unbroken chain from top to bottom, and from left to right, such that the content knows exactly how big it ought to be. This is quite an art in itself, so I won't go into it. A simple example where you have only one subview would be to pin its top, bottom, leading and trailing constraints to its parent, but as noted above if you're doing this, you might as well just set the type of the document view.
Now the fun bit. Select your document view and set its layout to 'Automatic'. Next, add top, bottom, leading and trailing constraints to its superview with a suitable value. I'm using zero, but you might want a small border. Finally, select the TRAILING and BOTTOM constraints you just made and set them to '>=' (greater than or equal) and a priority of 500 or less. The priority is very important, as it has to be less than the priority that the clip view uses to determine its own minimum size. Too high and the clip view will be forced to remain larger than its content, making it impossible in turn for the scroll view to be smaller than its content, rendering it useless.
The technical details aren't important. Just remember to set the document view to layout: automatic, pin all edges, and make the trailing and bottom constraints >= and priority 500.
Note that this will cause your content to hug the top-left corner.
Have you tried setting the document view's setTranslatesAutoresizingMaskIntoConstraints to TRUE?
[_scrollView.documentView setTranslatesAutoresizingMaskIntoConstraints:YES];

Resources