Let's say you've got a view with a single button, and you want that button to sit at the top center of the view. You set up the constraints using
constraintsWithVisualFormat: like so:
In iOS7 you get exactly what you want:
In iOS8 you end up with a button smooshed underneath the status bar:
What's going on? Apple changed the default behavior of how AutoLayout respects margins in iOS8. So now when you use
V:|-[_button] AutoLayout says "put a default amount of space between the superview and
_button, with no respect to the margins" where previously it would have first taken the margins of the superview into account.
There are a few things you can do about this. First there's a new property of
preservesSuperviewLayoutMargins which is set to
NO by default. On paper this seems like just the thing you need, but in testing I couldn't figure out what changing this to
YES actually did. So scrap that one.
Next, you can manually set the edge insets of your superview like so:
This works! But I really hate setting that top margin to a literal value. It seems safe enough now, but the old way seemed pretty safe too until it wasn't.
What we end up doing is setting the constraint to use the
topLayoutGuide property of the view controller instead of referencing the superview directly:
This works in both iOS7 & iOS8. The only kludgy part is that you need to set a property on your view that references back to the view controller so you can retrieve the
topLayoutGuide, but you can do that easily enough in an initializer.
You can see a complete example project here: https://github.com/richrad/AutoLayoutVFLMargins