Xcode, why some constraints are automatically added? - objective-c

Let's say i want to align a button (Delete) on the right border of every different device (3.5, 4, 4.5 inch etc.)
Should be very simple but, when i add a constraint to the right border:
New constraints are automatically added and i can see a dashed border rectangle on the top right of the view (which means that my button has been moved to the top.):
Why?? I don't need to add tons of contraints, i just want to align the button to the right and stay in the same position for every device.

You're seeing the red outline in the upper right corner because now that you've added one constraint Auto Layout needs additional constraints in order to know that you also want the button further down on the screen. You can accomplish this by also setting a constraint for position from the top, for instance.

Xcode is not "adding tons of constraints". It is doing what you said to do - and showing you that the results of doing that would be a disaster. It is telling you that you need to add more constraints or you'll have a mess on your hands.
Basically, as soon as you add one constraint to position/size an object, you must add sufficient constraints to position/size it unambiguously.
(Notice the warning/error messages in the document structure pane at the left, not shown in your screen shots. They are telling you something!)

You added constraints for the x position of the button. Now you have to add constraints for the y position of the button. An easy way that will most of the time work is to go into the auto layout bar at the bottom and clicking the third icon from the left. Then you click either add missing constraints or reset to suggested constraints.

Related

Handling autolayout special case

I have established constraints to like buttons, timestamp button, etc. below bottom of textfield a certain distance. You can see the issue in the image; if the textfield doesn't have enough letters, they overlap, how do I fix this? Here's a link to image:
https://docs.google.com/document/d/1_btZBSsL3SQA1IulFTasMFBghF_2hJYzrFlbuQPkKrM/edit?usp=sharing
The problem is setting the constraints with respect to the bottom of textfield. That bottom moves depending on the amount of text the field has and if that bottom position is above the bottom position of the icon to the left of the text field, you'll get the overlap you see. The solution, you might think, is to set the constraints with respect to the bottom of the icon but that won't work when the text field has a lot of text. You should try that just to understand the problem more clearly.
The actual solution is to set this particular constraint programmatically, as text is entered into the text field. You want to set that constraint with respect to the bottom of the view (icon or text field) that has the lowest bottom. That way, with little text, the constraint is set relative to the bottom of the icon but when there's enough text for the text field to vertically extend below the icon, the constraint is set relative to the text field instead.
Where would you set this constraint programmatically? Probably in the textField:shouldChangeCharactersInRange:replacementString: delegate method of UITextField.
Alternatively - and perhaps a better solution - you could have a view containing the icon and the text field and set the constraint in question with respect to the bottom of the container view. That way you can set the constraint in IB rather than have to do it programmatically.
To clarify my answer, after the discussion in the comments below, here's a picture of what I mean by having container views and setting constraints between them to avoid the observed overlap.
Set appropriate constraints within each of the container views then set constraints between the container views and between them and the cell content view (I'm assuming, from your picture, that you have all of this in a table view so you have some template table view cell).

Enforcing Auto Layout Constraints Across The View Hierarchy

I have two buttons that I want to be kept the same size, but the problem is that they have two different parent views. Autolayout seems to be ignoring the "equal size" constraint in this scenario. Constraining buttons with the same parent view works just fine.
I've created a very simple example that depicts what I am seeing:
As you can see from the above, buttons Two and Three are both set to have the same size constraint as button One. The only difference is that button Three is contained within another NSView. There are no width constraints that are linking button Three and its containing view.
However, when I run and resize the window, it looks like:
It doesn't matter whether I use the Interface Builder layout, or do it in code using the -[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:] method.
What am I missing? Is this not supported by Autolayout? Thanks a lot.
Edited: Added screenshot to indicate button Three's constraints.
This should work OK. I set up an example project to do the same thing. I have three buttons with equal width constraints between button one and button two. Then the same between button two and button three. Button one has a trailing edge constraint relative to it's parent view.
Note that between the second and third button, Interface Builder didn't let me do this in the main window. Instead, I had to do it using the document list on the left.
The result can be seen below:
Here's the link to the project:
https://github.com/MaxMacleod/ThreeButtonConstraintTest1
Couple of caveats. First, this is an iOS rather than an OS X project (I'm an iOS guy!). However the principles should be the same. Secondly, this doesn't pinpoint the exact reason why your project isn't working. However, if you can compare what this sample project does against yours, we can figure it out. I'll then update this answer. Better still if you could make your project available, I'd be happy to take a look.

Is there a way to shrink a constraint with autolayout without code?

Without using code, I'm basically trying to achieve the "Desired outcome" in this picture:
I want the constraint on the "Hello!" label to shrink its length when the screen height is shorter.
As you can see in "Actual result", the Button in the bottom is off the screen. I want the image view to have fixed width and height.
I know I can create IBOutlets for constraints and doing it by code like this kind of posts suggest (autolayout - make height of view relative to half superview height), but I'm trying to avoid using code as much as possible.
Side question: If there's no way to do this in IB, what are the best ways to do this in code?
Thanks for the help!
Yes. The easiest way to have this kind of "split height" constraint is to put a "header" view between your image view and the top of the screen, and embed your "Hello" label inside this new header view. Then add a constraint to keep the "Hello" label vertically centered inside the header view.
To keep the header view the right size, add constraints to keep the top of the header view pinned to the top of the screen, and the bottom of the header view to the top of the image view.
Then you'll just add constraints to keep the button and image view pinned to the bottom of the screen. (Or, see comment from Sulthan, below.)
In Xcode 5.1 (in beta), there is UI to make more general constraints, including the ones you want, but you have to do it like this or in code in earlier versions.

How to edit/modify NSLayoutConstraint in Xcode?

I drag a tab view into my custom view, and set its frame. Xcode automatically generate several NSLayoutConstraint objects those will decide its frame during auto-layout.
As shown above, a constraint which indicates the distance between right edge of the tab view and the RIGHT edge of its super view.
However, I do not want a constraint like this. What I want is a constraint which indecates the distance between the right edge of the tab view and the LEFT edge of its suber view. OR, the width of the tab view itself.
How should I do?
BTW, I tried delete the constraint, but Xcode generated this constraint back immediately. Therefore I could not add one (and actually I do not know how to add one, either).
There is a minimum number of constraints required on each axis of the view, hence you should add a new constraint first before deleting existing one to make sure Xcode understands how to layout the views properly.
Try to add a new constraint by clicking a view and then click on the middle button at the bottom right options in your screenshot:
go through following link, which explain auto layout..
http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

How to create labels with dynamic size in iOS 6 with autolayout

I'm having trouble with autolayout and labels that get their text set in the source code based on some external conditions. These layouts (portrait and landscape) look like this on the simulator:
http://imgur.com/l6Iirun
http://imgur.com/n7RwwSD
The second one is obviously not what I want it to be, the label with the URN should fill the whole screen.
I have a width constraint for the dynamic label added by Xcode which I can't get rid of even though the "Name"-label has a fixed width and all horizontal spaces are fixed as well which should logically rid me of the need to have a width constraint for the label containing the dynamic text.
Any help on how to achieve what I want? Thanks in advance!
It looks to me like your labels are not binding their trailing edge to the superview. In the lower right there is the little 'I beam' icon, click on your label and then that icon, the top of the menu should be 'Pin' and pick trailing edge to superview. The label should expand to fit the width of the screen, minus some padding. Once that is in place you should be able to remove the width constraint - although you may need to find it in the size inspector and select promote to user constraint before you can remove it.
If you don't see the pin menu, try going up to the top and picking Editor -> Pin and you should see it there.
If it is already pinned, try increasing the content compression resistance priority and decreasing the priority of the width - although if pinning it does not fix it then there is another constraint at play.