Master iPhone X Safe Area: UIKit & Auto Layout Guide for iOS Developers
This guide walks iOS developers through adapting apps for iPhone X by explaining safe area concepts, UIKit auto‑adjustments, Auto Layout with UILayoutGuide, code‑level APIs, Home Indicator handling, and provides practical code snippets and visual references.
Intro
A few days ago the SuiShouJi team finished the tense adaptation work for iPhone X. From running on the iPhone X simulator to full real‑device testing, we compiled a generic iPhone X adaptation document for reference.
Always Remember
Designing for iPhone X: to make your app run perfectly on iPhone X you must extend visual elements to fill the entire display while ensuring interactive controls and critical information are not clipped by the rounded corners, the notch, or the virtual Home indicator.
Updating your App to work on the new display (iPhone X) involves extending visual elements to fill the display's viewport, while also keeping controls and critical information from getting clipped in the corners or covered by the sensor housing or home indicator.
UIKit and Auto Layout
For native UIKit controls, adapting to iPhone X is straightforward. Standard controls such as navigation bars, tables, and collection views automatically adjust their layout on the iPhone X screen.
The image shows the navigation bar and bottom tab bar extending to leave space for the notch and home indicator.
When using Auto Layout, iOS 11 introduced a new UILayoutGuide property that solves the adaptation problem. var safeAreaLayoutGuide: UILayoutGuide { get } The safe‑area feature forms the foundation for iPhone X adaptation.
Safe Area
Apple’s Human Interface Guidelines describe the safe area as the region that ensures appropriate insetting based on the device and context, preventing content from underlapping the status bar, navigation bar, toolbar, and tab bar.
All apps should adhere to the safe area and layout margins defined by UIKit, which ensure appropriate insetting based on the device and context. The safe area also prevents content from underlapping the status bar, navigation bar, toolbar, and tab bar.
All applications should attach to the safe area and UIKit‑defined margins so that layouts are correct across devices and orientations, and the safe area guarantees that content does not overlap status, navigation, toolbars, or bottom navigation.
Another official document, “Positioning Content Relative to the Safe Area,” includes a diagram illustrating the safe area’s meaning.
Auto Layout with Safe Area
Standard system‑provided views automatically adopt a 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.
iOS 11 replaces bottomLayoutGuide and topLayoutGuide with safeAreaLayoutGuide. Existing layouts using the old guides can switch to the new guide without changes and gain full iPhone X compatibility.
When using Auto Layout, the storyboard now shows a “Safe Area” container at the bottom of each view controller’s hierarchy; subviews only need constraints to this guide to adapt perfectly.
Further screenshots illustrate how the safe area works with various view hierarchies.
Programming with Safe Area
For code‑based layouts, iOS 11 adds new APIs: UIView.safeAreaInsets and UIViewController.additionalSafeAreaInsets, which make programmatic adjustments easy.
var safeAreaInsets: UIEdgeInsets { get }You might use this property at runtime to adjust the position of your view's content programmatically.
Example:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let insets = self.view.safeAreaInsets
self.bottomButton.frame = CGRect(x: 0,
y: self.view.frame.size.height - 80 - insets.bottom,
width: self.view.frame.size.width,
height: 80)
}The additionalSafeAreaInsets property lets developers expand the safe area manually.
var additionalSafeAreaInsets: UIEdgeInsets { get set }Use this property to adjust the safe area insets of this view controller's views by the specified amount. The safe area defines the portion of your view controller's visible area that is guaranteed to be unobscured by the system status bar or an ancestor‑provided view such as the navigation bar. You might use this property to extend the safe area to include custom content in your interface. For example, a drawing app might use this property to avoid displaying content underneath tool palettes.
Example:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("Origin SafeAreaInsets : \(self.view.safeAreaInsets)")
self.additionalSafeAreaInsets = UIEdgeInsetsMake(5, 5, 5, 5)
print("view controller's additionalSafeAreaInsets set to \(self.additionalSafeAreaInsets)")
print("Adjusted SafeAreaInsets : \(self.view.safeAreaInsets)")
}Console output shows the insets before and after applying additionalSafeAreaInsets.
Origin SafeAreaInsets : UIEdgeInsets(top: 88.0, left: 0.0, bottom: 34.0, right: 0.0)
view controller's additionalSafeAreaInsets set to UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)
Adjusted SafeAreaInsets : UIEdgeInsets(top: 93.0, left: 5.0, bottom: 39.0, right: 5.0)Note that SafeAreaInsets values differ between portrait and landscape orientations. For a view controller they roughly follow:
// Portrait
SafeAreaInsets = (top: heightForTopBars + additionalSafeAreaInsets.top,
left: 0 + additionalSafeAreaInsets.left,
bottom: heightForBottomBars + additionalSafeAreaInsets.bottom,
right: 0 + additionalSafeAreaInsets.right)
// Landscape
SafeAreaInsets = (top: heightForTopBars + additionalSafeAreaInsets.top,
left: StatusBarHeight + additionalSafeAreaInsets.left,
bottom: HomeIndicatorAreaHeight + additionalSafeAreaInsets.bottom,
right: StatusBarHeight + additionalSafeAreaInsets.right)SafeAreaInsets Timing
If the view is not currently installed in a view hierarchy, or is not yet visible onscreen, the edge insets in this property are 0.
Thus
SafeAreaInsets</p> is only available after the view appears in the hierarchy.</p>
<p>Typical lifecycle values for <code>self.view.safeAreaInsetsare:
loadView → UIEdgeInsets(0,0,0,0)
viewDidLoad → UIEdgeInsets(0,0,0,0)
viewWillAppear → UIEdgeInsets(0,0,0,0)
viewDidLayoutSubviews → UIEdgeInsets(top:44, left:0, bottom:34, right:0)
viewDidAppear → UIEdgeInsets(top:44, left:0, bottom:34, right:0)Root View of a View Controller
For the view controller's root view, the insets account for the status bar, other visible bars, and any additional insets that you specified using the additionalSafeAreaInsets property.
For other views in the hierarchy, insets are non‑zero only when part of the view is covered by a non‑safe area; otherwise they are zero.
// Blue View SafeAreaInsets
UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
// Red View SafeAreaInsets
UIEdgeInsets(top: 88.0, left: 0.0, bottom: 0.0, right: 0.0)Home Indicator
iOS 11 adds a UIHomeIndicatorAutoHidden category on UIViewController to control automatic hiding of the home indicator, useful for full‑screen video or games.
@interface UIViewController (UIHomeIndicatorAutoHidden)
// Override to return a child view controller or nil. If non‑nil, that view controller's home indicator auto‑hiding will be used.
- (nullable UIViewController *)childViewControllerForHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);
// Controls the application's preferred home indicator auto‑hiding when this view controller is shown.
- (BOOL)prefersHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);
// Call this whenever the return values for the view controller's home indicator auto‑hiding have changed.
- (void)setNeedsUpdateOfHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);
@endNote that overriding prefersHomeIndicatorAutoHidden does not guarantee the indicator will be hidden; the system may still show it.
Discussion: Override this method to signal your preference for displaying the visual indicator. The system takes your preference into account, but returning true is no guarantee that the indicator will be hidden.
Apple does not provide an API to manually change the home indicator’s color; it automatically adapts to the background.
Some Height
Typical heights for UI elements on iPhone X versus normal devices:
UINavigationBar: 64 px normal, 88 px (96 px with large title) on iPhone X
UIStatusBar: 20 px normal, 44 px on iPhone X
UITabBar: 49 px normal, 83 px on iPhone X
Reference
Designing for iPhone X
iPhone X: Dealing with Home Indicator
SafeAreaLayoutGuide
Positioning Content Relative to the Safe Area
Human Interface Guidelines
Suishouji Tech Team
Suishouji's official tech channel, sharing original technical articles, posting recruitment opportunities, and hosting events. Follow us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
