Safe area layout guides in xib files - iOS 10 Safe area layout guides in xib files - iOS 10 ios ios

Safe area layout guides in xib files - iOS 10


There are some issues with safe area layout and backwards compatibility. See my comment over here.

You might be able to work around the issues with additional constraints like a 1000 priority >= 20.0 to superview.top and a 750 priority == safearea.top. If you always show a status bar, that should fix things.

A better approach may be to have separate storyboards/xibs for pre-iOS 11 and iOS-11 and up, especially if you run into more issues than this. The reason that's preferable is because pre-iOS 11 you should layout constraints to the top/bottom layout guides, but for iOS 11 you should lay them out to safe areas. Layout guides are gone. Laying out to layout guides for pre-iOS 11 is stylistically better than just offsetting by a min of 20 pixels, even though the results will be the same IFF you always show a status bar.

If you take this approach, you'll need to set each file to the correct deployment target that it will be used on (iOS 11, or something earlier) so that Xcode doesn't give you warnings and allows you to use layout guides or safe areas, depending. In your code, check for iOS 11 at runtime and then load the appropriate storyboard/xibs.

The downside of this approach is maintenance, (you'll have two sets of your view controllers to maintain and keep in sync), but once your app only supports iOS 11+ or Apple fixes the backward compatibility layout guide constraint generation, you can get rid of the pre-iOS 11 versions.

By the way, how are you displaying the controller that you're seeing this with? Is it just the root view controller or did you present it, or..? The issue I noticed has to do with pushing view controllers, so you may be hitting a different case.


Currently, backward compatibility doesn't work well.

My solution is to create 2 constraints in interface builder and remove one depending on the ios version you are using:

  • for ios 11: view.top == safe area.top
  • for earlier versions: view.top == superview.top + 20

Add them both as outlets as myConstraintSAFEAREA and myConstraintSUPERVIEW respectively. Then:

override func viewDidLoad() {    if #available(iOS 11.0, *) {        view.removeConstraint(myConstraintSUPERVIEW)    } else {        view.removeConstraint(myConstraintSAFEAREA)    }}


For me, a simple fix for getting it to work on both versions was

    if #available(iOS 11, *) {}    else {        self.edgesForExtendedLayout = []    }

From the documentation: "In iOS 10 and earlier, use this property to report which edges of your view controller extend underneath navigation bars or other system-provided views. ".So setting them to an empty array makes sure the view controller does not extend underneath nav bars.

Docu is available here