Safe Area Layout Guide

Apple introduced the topLayoutGuide and bottomLayoutGuide as properties of UIViewController way back in iOS 7. They allowed you to create constraints to keep your content from being hidden by UIKit bars like the status, navigation or tab bar. These layout guides are deprecated in iOS 11 and replaced by a single safe area layout guide.

Top and Bottom Layouts Guides - A Recap

An example of using the top and bottom layout guides with a view controller embedded in both a navigation controller and tab bar:

Top and Bottom Layout Guides

The green content view has a top constraint to the bottom anchor of the top layout guide and a bottom constraint to the top anchor of the bottom layout guide. The layout guides adapt to the presence of and size of the various bars.

Safe Area Layout Guide

New in iOS 11, Apple is deprecating the top and bottom layout guides and replacing them with a single safe area layout guide:

Safe Area Layout Guide

Our constraints are now with the top and bottom anchors of the safe area layout guide. This is not a big change but I think it is simpler to understand. You also have convenient access to layout anchors for the width, height and centers of the safe area.

Migrating Storyboards

Apple has tried to automate the change in Xcode 9 if you create the constraints in a Storyboard. Here are my constraints created in Xcode 8 for the earlier example:

Xcode 8 constraints

The constraints to the top and bottom layout guides have a standard spacing constant to create some padding:

Top Layout Guide constraint

I don’t know if this will change in the future but at the time of writing with Xcode 9 beta 2 you do not get a deprecation warning until you change your deployment target to iOS 11.0.

Apple told us in WWDC 2017 Session 412 that Storyboards using safe areas are backwards deployable. This means you can switch to using the safe area layout guide in Interface Builder even if you still target iOS 10 and older.

You convert from top and bottom layout guides to the safe area layout guide by changing the setting in the file inspector for the Storyboard. You need to do this for each Storyboard in your project.

Enable Safe Area Layout Guides

The Storyboard automatically replaces the top and bottom layout guides with a safe area and updates the constraints:

Safe Area Constraints

Missing Spacing

Unfortunately the migration is not without problems. Constraints to the safe area layout guide do not seem to cope with standard spacing. Inspecting the constraint shows it as having a standard spacing:

Standard spacing

But the space is missing when the layout runs:

Missing spacing

This seems like a bug (rdar://32970194) in Interface Builder as it does not allow you to create constraints to the safe area layout guide with “standard” spacing. The workaround is to manually add back the missing spacing to the top and bottom constraints:

Manual spacing

Hopefully Apple fixes this in a future update as manually fixing this for larger projects will be painful.

Creating Constraints in Code

If you create your constraints in code use the safeAreaLayoutGuide property of UIView to get the relevant layout anchors. Let’s recreate the above Interface Builder example in code to see how it looks:

Assuming we have the green view as a property in our view controller:

private let greenView = UIView()

We might have a function to set up the views and constraints called from viewDidLoad:

private func setupView() {
  greenView.translatesAutoresizingMaskIntoConstraints = false
  greenView.backgroundColor = .green
  view.addSubview(greenView)

Create the leading and trailing margin constraints as always using the layoutMarginsGuide of the root view:

  let margins = view.layoutMarginsGuide
  NSLayoutConstraint.activate([
    greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
    greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
    ])

Now unless you are targeting iOS 11 only you will need to wrap the safe area layout guide constraints with #available and fall back to top and bottom layout guides for earlier iOS versions:

  if #available(iOS 11, *) {
    let guide = view.safeAreaLayoutGuide
    NSLayoutConstraint.activate([
     greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
     guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0)
     ])
  } else {
     let standardSpacing: CGFloat = 8.0
     NSLayoutConstraint.activate([
     greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing),
     bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing)
     ])
  }

Notes:

  • The safeAreaLayoutGuide is a property of UIView where topLayoutGuide and bottomLayoutGuide are properties of UIViewController. The beta seeds of iOS 11 also have a safeAreaLayoutGuide property on UIViewController but this is deprecated.
  • The constraintEqualToSystemSpacingBelow method is new in iOS 11 and removes the need to hard code standard spacing. There are also less than and greater than versions. For horizontal spacing there is also constraintEqualToSystemSpacingAfter.
  • If you have a custom toolbar you can increase the size of the safe area with the additionalSafeAreaInsets property on UIViewController.

More Details