Using float values in storyboard - xcode

I want to to assign a float value to a UIButtons frame in Storyboard.
But I can only use int values. Is it discouraged to use .5 for example? because I have some buttons and I want to place them according to the original photoshop design.
for example I have a button I need to be placed at X:151 , how can I achieve that?

Do NOT use a float value. As you have rightly observed, Interface Builder prevents this; but you should not do it even in code. Just the opposite: when you assign a frame (or related component) in code, you should set it to an integral value first. (In fact, there are even functions such as CGRectIntegral to help you.)
The reason is that otherwise you can end up between pixels on the screen, and the view will not display correctly (because there is no such thing as half a pixel). Stick to whole numbers of points so that you are using whole numbers of pixels.

Do it programmatically (click here for example), I don't know the reason why storyboard prevents from using non-integer values for frame ingredients, however I do know three things:
It works programmatically. (just assign a dummy value in storyboard and overwrite it in code later on.)
Apple uses non-integer values for their native objects in iOS, for example the line separator between cells in table view is 0.5 point height.
Points are not pixels (response to the accepted answer, according to the time of writing these lines.)

First of all I was not able to find a solid reference of Not using float value on storyboard. So following a workflow/procedure to achieve float value on storyboard. Last tried with Xcode Version 7.3.1 (7D1014).
Select the view. Remove any previous constraint for the UIView if any. Then add all the constraints including the floating value. On my case it was Leading, Trailing, bottom and Height. Only Bottom have a Int value others are float. Press the "Add X Constraints" button.
Finally I have the following:
The problem is that whenever I want to edit the value, I have to remove all the previous constraints and add them again according to the new constraints.

Related

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

NSTextField resizable to fit content

I have NSTextField with left, right and top constraints defined (no bottom constraint set). I need NSTextField to grow if content can't fit in it and decrease size if there is unused space left.
Now I have: NSTextField automatically expands with strange behavior if it has multi-line text or too much content, also NSTextField doesn't decrease own's size on window resize.
I haven't found any simple solution written on Swift to solve that problem (I have a lot of such labels with constraints), at iOS everything was working with usual text labels and constraints.
I've created simple project for that question that you can see the problem: [Download Text.zip]
The solutions I've found but not used:
You can try to calculate possible TextField height and set height constraint for it. Problems of that solution:
Possible height calculations are inaccurate, sometimes you calculate incorrect height.
Solutions are written on Objective-C with some complex code.
Run .sizeToFit() on each window resize or text change action. It's not working because .sizeToFit() always compress all text to single line.
Use NSTextView instead of NSTextField. It's good way, but:
I don't need scrolling, editing and other functional of NSTextView. I don't want to call to complex component for simple label.
NSTextView always wants height or bottom constraint, I don't know bottom constraint because content can expand down with new text.
I haven't find full solution to make NSTextView's behavior like I want :)
According to Mac OS X Release Notes (section NSTextField intrinsicContentSize improvements) it’s known bug when height of NSTextField is changed, but width is remained the same. We have two ways to fixing it:
We can specify maximumNumberOfLines to a value that makes sense. That is not good way to us because we don’t know actual number of lines and don’t want to calculate it.
We can set preferredMaxLayoutWidth to a real value. I’ve ended with such code:
Code:
override func viewDidLayout() {
super.viewDidLayout()
textField.preferredMaxLayoutWidth = textField.frame.width
}

Auto-layout issue with UIButton with long title that compresses an aligned Segmented control which should have fixed width and should never compress

In my Xcode 6.2 Swift project I have an issue with Auto-layout (I'm also using size classes) that I'm not able to figure out...
In Main.storyboard I have a view containing, among the others interface elements, a UIButton and a UISegmentedControl that are positioned at the same height on the opposite side of the view.
I'm setting manually all the constraints in Interface Builder (none in code) and my every view is working just fine, except in this case (and this particular issue only occurs when I have a long text).
The button is aligned to the left border of the view and its constraints are:
Leading space to superview == 0
Trailing space to segmented controller >= 8
Top and bottom space to other interface elements == 8
The segmented controller (which has 2 segments) is aligned to the right border of the view and its constraints are:
Trailing space to superview == 0
Leading space to button >= 8
Top and bottom space to other interface elements == 8
The button in the storyboard has a title "Some title", but actually the actual title is always set in code in ViewWillAppear:
myButton.setTitle(aStringThatSometimesIsPrettyLong, forState: .Normal)
The visual result I need to achieve (on every possibile device and orientation) is that the Button title I set in code, while it can be displayed in good length in the interface, should never compromise the size of the segmented control, compressing the labels of the two segments.
So, I want the size of the segmented control to be fixed and I'm willing to accept the fact that the Button title, if long, can be truncated with dots.
Instead, no matter what I try (and I'll explain what I've tried in a moment) when the Button title is very long it is not truncated, instead the segmented control is compressed and therefore its two segments labels are truncated.
So far, I've tried, separately and together, these steps:
Adding a width minimum constraint to the segmented control.
Incremented (in steps, up to 1000) the Content compression resistance of the segmented control while decreasing the correspondent value of the button.
Increased (up to 1000) the Content hugging priority of the button.
I think I can't set a maximum width to the Button, because it can stretch depending on the title set in code and, more important, on what device the app is run on.
My biggest issue is that, no matter what I try, when I run the app I always get the same behavior (button title completely shown, un-truncated, and compressed segmented control). It seems like adding these constraints doesn't change anything, and it never happened to me before with Auto-layout... messing up, a lot, but no change adding constraints, this is new!
Maybe the issue is that the button title is set in ViewWillAppear and not in the Storyboard, but my app wouldn't work properly if I couldn't set its title in code.
Last, but pretty important, I have to admit that, while I've managed so far to get Auto-layout and Size classes working on all devices and orientations for all the (over 10) viewcontrollers of my app, I've actually never written a single line of code for Auto.layout and Size classes: I've done everything in Interface Builder and, if possible, I'd really love to continue this way.
Any suggestion would be really, really appreciated!
Thanks in advance,
Cesare
As #KenThomases pointed out, the constraints I was setting were actually right (actually, it also works with less constraints now that, thanks to his answer, I figured out the issue), but the Segmented control wasn't getting its intrinsicContentSize. Fixed that, now everything's fine.

Why are two buttons constrained with a ZERO distance between them, not flush?

I have read in numerous places that constraints in Cocoa AutoLayout act on the visual bounds of the control/view in question so the below is perplexing (2me):
In Xcode IB, I add/drag two (push button) buttons to a view (one underneath the other) and constrain them such that they have zero distance between themselves vertically. I expect two buttons that are flush against one another in the vertical direction.
The result is two buttons that DO have a small difference/space between them which can be verified visually or by looking at the alignment rectangle values in Xcode. In this instance the additional distance between them appears to be 1 point.
Below is a screenshot of the constraints amongst the simple view hierarchy:
Further, confirming the above, when you change the constant in the constraint to -1, the two buttons appear flush with one another.
The above is on OS X 10.10 (Yosemite).
Stranger still, in my actual application (the above is just a test case for the SO question) when I stack many NSButton vertically (programmatically and not via IB) I need to provid a constraint of -4.0 between them (as opposed to the -1.0 above) to make them flush. The bezelStyle for this button is as follows (Swift):
self.bezelStyle = NSBezelStyle.RoundedBezelStyle
[Although it doesn't make sense, I would be much more comfortable if it were uniformly -1.0 needed to make them flush!]
UPDATE I:
I think I have found why my application is behaving differently to the test example. I have used a NSBezelStyle.RoundedBezelStyle in code and set its height to be 24.0; various things point to this button style/type needing to have a fixed height (see IB where the height parameter is greyed out and fixed at 21.0 and cannot be changed!) The difference between 24 and 21 is 3.0 which is exactly what we are seeing is the difference in main application constraints -4.0 relative to rest example required -1.0
The moral of the story: don't use RoundedBezelStyle outside certain usage scenarios where variable height is needed! PostScript: RoundedRectBezelStyle seems to suffer the same malady!
That still leaves the question of why certain buttons in the test example are not flush with a constraint of -1.0 being required...
UPDATE II:
Further testing shows that I get different results depending on which "type" of button I choose. In code this would be linked to the bezelStyle property of the button.
The gradient button sits flush with a constraint of zero between buttons
The textured button seems to need to need a +1.0 constraint between buttons to avoid overlap
Most of the other buttons (especially those with rounded bezel styles) seem to need constraint of -1.0 between themselves to be flush
REVISED QUESTION (based on my findings):
Are the above intentional from Apple (is there some logical/rational explanation) OR are they bugs?
If the above is true, is it bad practise to code my user-interface (a spreadsheet-like grid) with these fudges for "flushness" built-in to how I layout my view?
How a view lays out in regards of it's bounds is up to the view itself.
What you have seen is the style of the button not covering then entire frame set up by autolayout. That is correct behaviour.

cocoa: weird purple constraint for split view

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.

Resources