Working with constraints in interface builder

2019-04-28 15:43发布

问题:

So, I can't get my head around constraints in interface builder.

I can't add them myself - interface builder seems to think that it knows best.

I also can't take them away (I can convert to a "user" constraint, then delete, but interface builder will just replace it with the same constraint again).

I thought constraints were supposed to help you with changing layouts and all sorts - i.e. building views for iPhone 5 and earlier ones. Also, moving from portrait mode to landscape mode.

I can't seem to get it to work at all. If I add a view and I place it below the top of the superview then it will set a Top space to: constraint. This will be a pixel value which means that when I view on the shorter iPhone 4 (or if the phone turns landscape) these elements don't auto move up.

For instance, I am trying to create a custom keyboard view - one similar to that you would see on a cash register. I have created a custom UIView subclass and now I have put a UIView into interface builder. I have set the height and width and positioned it at the bottom of the view (where it "clicked" into place). How interface builder has added a Top space to constraint putting it at that height (iphone 5). So if I view it on the iPhone 4 it doesn't budge up (as I would expect, as I "snapped" it into place at the bottom of the screen) but instead cuts off the bottom.

This isn't what I wanted, but (as above) I can't delete the constraint unfortunately.

What can I do? I am aware that I could just create two nib files (for iPhone 5 and for other iphones) but what about when I want things to auto-budge when I turn the phone landscape?

Thanks for your help

回答1:

You can't remove a constraint in Interface Builder if doing so would leave insufficient constraints to determine completely the size and position of any interface widget.

  • One solution: add more constraints, until the size and position are overdetermined. You will then be able to delete one of the superfluous constraints. For instance, you gave this example:

    I have set the height and width and positioned it at the bottom of the view (where it "clicked" into place). How interface builder has added a Top space to constraint putting it at that height (iphone 5). So if I view it on the iPhone 4 it doesn't budge up (as I would expect, as I "snapped" it into place at the bottom of the screen) but instead cuts off the bottom.

    Select the view and choose Editor > Pin > Bottom Space to Superview. Now you have more constraints than you need: the height, the width, something determining the horizontal position (which you forgot to mention), and a pin to the top of the superview and a pin to the bottom of the superview. Thus you can now delete the pin to the top.

  • Another solution: remove the unwanted constraints in code. A constraint is an ordinary interface object, so you can make an outlet to it and remove it when your code runs. However, if you do this in such a way as to leave the size or position underdetermined, you will get unpredictable results ("ambiguous layout"), so be careful.

  • Still another solution: reduce the priority of unwanted constraints in IB. Interface Builder will ensure that all values are absolutely determined. But perhaps you know, for example, that the superview will change size and so some of the constraints created by Interface Builder will be undesirable. You can't delete them, but you can reduce their priority. Thus, in your example, you might end up with a pin to the top and a pin to the bottom, but you could then just reduce the priority of the pin to the top.



回答2:

Non-obvious to me was that you can turn this new feature off on a per-nib file basis if it is more trouble that it is worth.

Select the nib file and choose the File inspector (View->Utilities->Show File Inspector) and de-select "Use Autolayout".



回答3:

If you are having trouble with this on different screen sizes where it builds fine on an iPhone 5 screen but not on an iPhone 4 screen or visa versa one solution is to turn off the 'Autoresize Subviews' option for the offending views and then to click the button on the bottom right of the window that shows your storyboard/nib that changes the screen size and make sure that everything looks fine for both screen sizes. Just another one of those things that makes me happy when I build things all in code and avoid IB oddities like this.