Why is this combination of constraints ambiguous? - ios

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.

Related

How many minimum constraints are required for one UI object ? (iOS)

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.

AutoLayout Understanding Multiplier

I have a problem with multiplier and cannot understand how this feature works. For example i have view has 6:1 multiplier(To SuperView.Leading) as below.
When i change the multiplier to 2:1 it seems like below picture.
My question is in the 6:1 relation what does 6 and 1 mean. And also in 2:1 relation what does 2 and 1 mean. Similar consider you have three view like the picture below. Totally there 4 blank areas between subViews and superView. How can i say every blank area must be the SuperView.Width / 6 (and every blank width must be equal)
Thanks in advance.
When working with autolayout, especially when you are working with proportional layouts, you have to use multiplier.
I have to explain here some mathematics.
We know straight line equation.
Y = Mx + C
In above equation. Assume M is your multiplier and C is your Constant.
Thus suppose you have superview (in case of iphone 6s plus) of
414(width) x 736(height) size. On that view suppose you created subview.
Now if you want subview size exacly half of superview size, then just drag two constraints from subview to superview. (i.e. Equal Width and Equal Height)
See this Image
Obviously now you will get an error. just like I'm getting. (See below Image)
Now click on both of the constraints one by one, and use multiplier as 0.5. Then use above straight line equation.
Here 0.5 means you want width of subview = superviewWidth / 2.0 i.e. 207 px.
In other words you can provide multiplier as 207:414 also.
Y i.e. subviewWidth = ((M i.e. 0.5) * (x i.e. 414 i.e. superviewWidth)) + (Constant i.e. Zero)
Finally you get subviewWidth = 207 px
Similarly do for height of subview. Provide multiplier 0.5 or 368:736.
When done all things, don't forget to click on subview and update frames.
This way constants and multiplier will works.
Multiplier is there for creating Proportional Constraint. Auto Layout calculates the first item’s attribute to be the product of the second item’s attribute and this multiplier. Any value other than 1 creates a proportional constraint.
In your case, 6:1 means multiplier is 6/1 = 6. Which means
view.leading = Superview.leadingMargin*6
replace : with / - you will understand what it means.
In my example multiplier is 1:2 = 0.5
height red view is 0.5 times greater than the superview
When it comes to the multiplier it depends on what constraints you are dealing with. You have the views leading constraint connected to the superview leading margin. When the constant is 0 that gives you an 8 points gap. When you change the multiplier you will be effecting that gap. That's why when you do 2:1 you see it go to the right 8 points. Essentially multiplying the original 8 point gap by 2. If you do 1:2 it will go from 8 points to 4 points, essentially dividing the original 8 point margin by 2.
Now when you look at Adrians example, he only multiplied it by 1:2 so how did that make it half of the entire screen? That's because he did that on the height constraint. The view was originally the full size of the superview, but when he multiplied it by 1:2, he indicated that he wanted it to be 1/2 of its original height. Giving you that end result.
So the important thing to understand is that multiplier may seem to act different depending on the situation but that's because it depends on what constraints you are dealing with.
here is a good answer that goes into this more:
Understanding multiplier in auto layout to use relative positioning
the link details how if you wanted to make the leading edge 10% and trailing edge 90% you would need to set both constraints in relation to the trailing edge.
Multiplying the trailing constraint by 0.9 and the leading constraints by 0.1.
In regards to your question about the equally separated views, you should use a stack view. They were made for situations like this so you didn't have to deal with all the constraints. You just need to set constraints for the stack view and configure it accordingly.

Setting up variable constrains in xcode

I'm having trouble setting up constraints.
This is the thing I am trying to achieve:
I have 2 objects A and B. I want there there to be a maximum of 100 points between A and B if its a larger screen, or less if its a smaller screen.
Also, I want there to be a minimum of a 20 point margin from the main view controller. So on a smaller screen the minimum spacing will be 20 points, and on a larger screen the margin can be as wide as needs in order to satisfy the space between A and B at 100 points.
To illustrate how I want it to look on various screens:
4 inch screen
I want there to be a 20 point margin on either side and the middle (space between A and B) can be variable, i.e. 100 or less.
5.5 inch screen
The margins can be variable and expand as large as they need to, but the middle section (space between A and B) can be a maximum of 100.
Any help how to achieve this would be greatly appreciated.
This can be achieved with help from three dummy views and two width constrains with different priorities. I set up a test project to test my thought. check it out to see whether it's what you needed
https://github.com/dopcn/testSeg

How do I make a constraint "5-53" space between views?

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.

Autolayout ambiguity with inequalities

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.

Resources