when I want to make a constraint saying that the layout system can have minimum 5 and maximum 53 points between two views, such as
ViewA.Leading is greater or equal ViewB.Trailing 5 (pri 1000 multiplier 1)
ViewA.Leading is less or equal ViewB.Trailing 53 (pri 1000 multiplier 1)
Interface Builder always gets upset with me, giving me the "Inequality Constraint Ambiguity" error. If this is not the way to make such a constraint, how should it be instead?
(please, I insist on expressing the constraints in a storyboard through Interface Builder)
Cheers
Nik
The ambiguity is that the auto layout system doesn't know exactly how much space to put. You have successfully placed limits on the range of allowed space, but there are still any number of solutions. For example, 20 points works, but so does 40, and so does 31.2875.
The system needs additional information to pick a specific distance. How much space, specifically, would you prefer if all other constraints allow flexibility?
You could, for example, set a constraint ViewA.Leading equal to ViewB.Trailing plus 20 but at a lower priority. The lower priority would allow it to be overridden by higher priority constraints and things such as content hugging or compression resistance priority. But, all else being equal, the system will try for 20 or as close to 20 as possible. That removes the ambiguity.
But, ultimately, you need to decide how the system should resolve things when there are remaining degrees of freedom and give the system the corresponding constraints to eliminate that freedom, so it can come up with one right answer.
Related
Most of the interviews common question is "How many minimum constraints are required for one UI object" Can someone please clarify?
Regardless of what are the constraints (how would you determine the appropriate constraints), basically, the minimum required constraints are the constraints that should determine the size and the origin of the component (height, width, x and y).
Keep in mind it is not only required to specify each property by its own literal constraint, for example, you could determine what is the width of the component by setting leading and trailing constraints to it instead of equals constant width. Furthermore, components with intrinsic content size should not have always fixed size (height and width), hence determining their origins (x and y) would be sufficient, unless there is a need to setup their constants.
To be short, excluding the case of an UIScrollView where the content size is involved as well, you need 2 distinct constraints per axis (horizontal and vertical).
It's also important to note that if an UI element has an intrinsic size, that counts as a constraint for that axis already, even though it can be overridden with constraints that have higher priority.
So, I am trying to make a view like this that is scalable on all the iPhone devices from iPhone X to iPhone SE.
The three constraints are marked on the screen named 1, 2, and 3. All three of these constraints have Greater than equal to attribute set to have a minimum buffer of 5 points from the margins.
Now, I would like to see this view on iPhone SE, the iPhone 8 family, and the plus family but I would like to specify that:
constraint 1 should decrease in size first,
constraints 2 should decrease in size second, and
constraint 3 should decrease in size third
I tried multiple configurations with the priorities, and even though my intuition tells me that there might be a solution in the content hugging and compression resistance values, these are not available for the constraints themselves.
How can I accomplish this on the interface builder?
It is possible, but you need two constraints per flexible distance you want. Try set it up as follows:
1a. Vertical space constraint >= min, priority 1000
1b. Vertical space constraint = max, priority 900
2a. Vertical space constraint >= min, priority 1000
2b. Vertical space constraint = max, priority 910
3a. Vertical space constraint >= min, priority 1000
3b. Vertical space constraint = max, priority 920
Where min is the minimum distance you want, and max is the maximum distance. 1a and 1b corresponds to your constraint 1 and so on.
Note two things, if you view becomes smaller than is allowed with all priorities on min you will get layout errors. If the view is larger than all maxvalues, the first distance (lowest priority) will extend.
I am new to autolayout and I want to understand the constraints of autolayout.
my question is ->
When we apply constraints between two objects it gives you 3 options in relation tab which are equal, less than or equal to and greater than equal to.
So I want to understand when to use less than or equal to and greater than equal to sonstraint.
If possible please help me with some small demo.
I think this will help you.
suppose you want a UILabel to resize maximum height to 80 pixels depending upon its inner content and if more test are displayed in the label then it should truncate its tail but should not increase its height because you have other elements on screen which will not look good if the label will increase more then that. So here you should use height <= 80. So if you set some minimum value of the label like height >= 40 so if the text of the label is not enough to fit in 40 height then it will stay 40 pixels but if text increases then it will increase max up to 80. So here you came to now about the use of greater then or equal to also. Like if you want a element to be minimum some value and if its resizing at runtime then should not be less then any value, then you can use those constraints. I can describe in brief if needed. Thanks.
XCode 7
Do you know why this is being considered ambiguous?
I defined that I wanted it centered horizontally and vertically... nothing should be questionable there... then I defined that I wanted it 650 points or larger in horizontal and vertical... so why the ambiguity?
** EDIT **
I'm following up with some more images based on a comment below.
Notice that ambiguity appears to be resolved, yet I get no output on the screen which should be filled edge to edge with a map view.
You chose an inequality constraint of greater than or equal to. Since the size could change, (be greater than 650 height or width) it is considered ambiguous. If you set it equal to 650, it should no longer be considered ambiguous.
I'm confused about how Cocoa's Autolayout determines whether a layout is ambiguous. Here's a simple example:
The observed behavior is as follows. The spacers to the left and right of the green rectangle are always the same width. When you stretch the superview horizontally outwards, the spacers stick to 80 while the rectangle expands. When you shrink the superview horizontally, the rectangle sticks to 398 while the spacers shrink to 10, after which the rectangle continues to shrink. At no point is the layout labeled ambiguous by IB.
However, you'll notice that the horizontal layout is defined almost entirely by inequalities! From what I can see, when the rectangle has a width of > 398, there's no reason for the spacers to have a width of 80. They could have a width of anywhere from 10 to 80 and still satisfy each horizontal inequality. That sounds ambiguous to me, but IB clearly does not agree.
There must be some implicit rule I'm missing. Please help me out!
Auto layout has, coincidentally, ambiguous documentation. Therefore, the behavior you observed from your application is technically undefined. Here is exactly what the documentation says:
Constraints have a priority level. Constraints with higher priority levels are satisfied before constraints with lower priority levels. The default priority level is required (NSLayoutPriorityRequired), which means that the constraint must be satisfied exactly. The layout system gets as close as it can to satisfying an optional constraint, even if it cannot completely achieve it.
The requirements are therefore
The layout system gets as close as it can to satisfying an optional constraint
Constraints with a priority of 1000 must be satisfied exactly
Higher priority constraints are satisfied before constraints with lower priority levels
However, as you have noticed
What causes the spacer to greedily expand to 80, versus the green rect expanding maximally on account of it having a higher priority?
Auto layout does not define "close as it can" and "Higher priory constraints are satisfied before constraints" in a unambiguous manner. The Auto layout documentation mentions these two dimensions: priority and closeness; but these documents do not say how the optimization of these dimensions interact.
With that being said, here is one theory of how auto layout could operate based on the fact that auto layout is probably a multi-variable linear decomposition solver.
Let's consider your corner cases
When you stretch the superview horizontally outwards the spacers stick to 80 while the rectangle expands
When you shrink the superview horizontally, the rectangle sticks to 398 while the spacers shrink to 10
after which the rectangle continues to shrink
These corner cases can be reduced to
Case A - superview > 398+80+80 (Spacers fixed at 80, rectangle expands from 398)
Case B - superview > 398+10+10 (Rectangle fixed at 398, spacers contract from 80 to 10)
Case C - superview <= 398+10+10 (Spacers fixed at 10, rectangle contracts from 398)
Notice how the numbers never jump from case to case. There is a smooth connection from Case A to Case B in the spacers, going from 80 -> 80 at the critical points. The same occurs for the rectangle from Case B to Case C. The algorithm used by auto-layout always results in a smooth solution when dealing with critical points.