Apple recently released iOS 11.0 to the public on September 19, 2017, bringing with it a plethora of API changes to system frameworks that every iOS Engineer interacts with on a daily basis — namely UIKit and Foundation.

This release came alongside the announcement of the iPhone X’s edge-to-edge display and gesture-based home button, which introduced entirely new interaction paradigms that required significant changes to UIKit to support.

It’s therefore important to understand exactly what has changed and why. Apple’s WWDC 2017 sessions do an incredible job of providing a lot of insight into these changes, but it can be difficult, and time consuming to get a holistic view of the specific differences that were made and how they might affect developers as they’re deep in the trenches writing code.

I’ve spent a bit of time comparing UIKit.framework’s iOS 10.3 API to its iOS 11.0 API, inspecting the diffs line-by-line with a magnifying glass and learning as much as I can about the changes so that you don’t have to. In this article I dive into what’s new in UIViewController.h

tvOS Additions

These are changes that were made specific to tvOS, and don’t apply to iOS or watchOS.

UIModalPresentationBlurOverFullScreen

UIModalPresentationBlurOverFullScreen __TVOS_AVAILABLE(11_0) __IOS_PROHIBITED __WATCHOS_PROHIBITED

 

A new UIModalPresentationStyle that has been added specific to tvOS called UIModalPresentationBlurOverFullScreen. This presentation style is unavailable on watchOS and iOS. It is described as “A presentation style that blurs the underlying content before displaying new content in a full-screen presentation.”

Documentation

preferredUserInterfaceStyle

@property (nonatomic, readonly) UIUserInterfaceStyle preferredUserInterfaceStyle API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios, watchos); // Defaults to UIUserInterfaceStyleUnspecified

A new property that has been added specific to tvOS to indicate the ‘interface style’ for the view controller. Changing this property allows a tvOS application to let the system manage the interface style, or manually override and specify either light or dark mode.

UIUserInterfaceStyle is an enum which was added in tvOS 10.0 has the following cases:

// An unknown interface style.
case unspecified
// The light interface style.
case light
// The dark interface style.
case dark

Documentation

childViewControllerForUserInterfaceStyle

@property (nonatomic, readonly, nullable) UIViewController *childViewControllerForUserInterfaceStyle API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios, watchos);

A new property that has been added specific to tvOS. This property can be overridden by Container View Controllers to return a Child View Controller that supports the current preferredUserInterfaceStyle.

Documentation

setNeedsUserInterfaceAppearanceUpdate

- (void)setNeedsUserInterfaceAppearanceUpdate API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios, watchos);

A new method that has been added specific to tvOS. It should be called whenever the new preferredUserInterfaceStyle property changes to trigger the UI to update.

Documentation

Updated Documentation

These are changes that don’t affect API functionality, but including existing documentation being updated to provided new information or recommended usage patterns.

viewControllerForUnwindSegueAction

- (nullable UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(nullable id)sender NS_DEPRECATED_IOS(6_0, 9_0);

This (deprecated in iOS 9.0) API itself hasn’t changed but the comments have been updated to state that applications running on iOS 9.0 or later should no longer override this method on a UIViewController subclass. Instead overriding -allowedChildViewControllersForUnwindingFromSource: to assist UIKit in finding a descendant view controller to unwind to.

Documentation

segueForUnwindingToViewController

- (nullable UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(nullable NSString *)identifier NS_DEPRECATED_IOS(6_0, 9_0);

This (deprecated in iOS 9.0) API has also not changed, but the comments have been updated to state that applications running on iOS 9.0 or later should not override this method on a UIViewController subclass but instead override -unwindForSegue:towardsViewController: to modify itself as part of an unwind segue.

Documentation

Keyboard Dismissal

Changes related to keyboard dismissal, of which there is only one.

disablesAutomaticKeyboardDismissal

@property(nonatomic, readonly) BOOL disablesAutomaticKeyboardDismissal NS_AVAILABLE_IOS(4_3);

This BOOL property is now readonly and can only be changed by overriding the property in a UIViewController subclass. This property affects the UIModalPresentationStyleFormSheet behavior. By default when a UIViewController is presented with the FormSheet presentation style, if a user taps into a UIControl (such as a UITextField) that no longer requires the keyboard, the keyboard will not be dismissed. Overriding the property allows this behavior to be changed.

Documentation

Scroll Views

Changes related to the behavior of Scroll Views.

automaticallyAdjustsScrollViewInsets

@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED_WITH_REPLACEMENT(“Use UIScrollView’s contentInsetAdjustmentBehavior instead”, ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES

This BOOL property is now deprecated and is replaced with UIScrollView’s contentInsetAdjustmentBehavior. Previously this property would be used when a UIScrollView was placed inside a UIViewController to adjust the Scroll View’s contentInset and scrollIndicatorInset, allowing a Scroll View’s content to start where the UINavigationBar ends, but also to scroll underneath the Navigation Bar to the edge of the UIViewController’s view.

UIScrollView now has a property in iOS 11.0 called
var contentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentBehavior { get set }

As described, “This property specifies how the safe area insets are used to modify the content area of the scroll view. The default value of this property is automatic.”

UIScrollViewContentInsetAdjustmentBehavior is an enumeration with the following cases as options:

// Automatically adjust the scroll view insets.
//
// Content is always adjusted vertically when the scroll view is the // content view of a view controller that is currently displayed by // a navigation or tab bar controller. If the scroll view is
// horizontally scrollable, the horizontal content offset is also 
// adjusted when there are nonzero safe area insets.
case automatic
// Adjust the insets only in the scrollable directions.
// The top and bottom insets include the safe area inset values when // the vertical content size is greater than the height of the 
// scroll view itself. The top and bottom insets are also adjusted // when the alwaysBounceVertical property is true. Similarly, the 
// left and right insets include the safe area insets when the 
// horizontal content size is greater than the width of the scroll // view.
case scrollableAxes
// Do not adjust the scroll view insets.
case never
// Always include the safe area insets in the content adjustment.
case always

Documentation

Safe Areas

Changes related to Safe Areas, likely introduced due to the iPhone X’s new display paradigms such as dynamic UINavigationBar heights and the Home Indicator.

topLayoutGuide

@property(nonatomic,readonly,strong) id<UILayoutSupport> topLayoutGuide API_DEPRECATED_WITH_REPLACEMENT(“-[UIView safeAreaLayoutGuide]”, ios(7.0,11.0), tvos(7.0,11.0));

topLayoutGuide has been deprecated and replaced by safeAreaLayoutGuideon the UIViewController’s view. Previously this property was used to specify the top-most point in a UIViewController that content could be placed without appearing behind a translucent UINavigationBar. Using AutoLayout subviews could be constrained to this guide in order to place Views in relation to the guide.

Layout Guides in iOS 11.0 are now managed and controlled in a more granular approach on every UIView.

Documentation

bottomLayoutGuide

@property(nonatomic,readonly,strong) id<UILayoutSupport> bottomLayoutGuide API_DEPRECATED_WITH_REPLACEMENT(“-[UIView safeAreaLayoutGuide]”, ios(7.0,11.0), tvos(7.0,11.0));

bottomLayoutGuide has also been deprecated and replaced by safeAreaLayoutGuide on the UIViewController’s view. Previously this property was used to specify the bottom-most point in a UIViewController that content could be placed without appearing behind a transparent UITabBar, or UIToolbar. Using AutoLayout subviews could be constrained to this guide in order to place Views in relation to the guide.

Documentation

additionalSafeAreaInsets

@property(nonatomic) UIEdgeInsets additionalSafeAreaInsets API_AVAILABLE(ios(11.0), tvos(11.0)); ```

A new property of type UIEdgeInsets that has been added, which enables UIViewController subclasses to specify additional insets to be added onto the safeAreaInsets. This may be used in order to extend a View Controller’s safe area to include custom app content such as in a drawing app, increasing the safe area to avoid displaying content underneath tool palettes, or in a game to avoid display content over a HUD (Heads Up Display).

‘Safe Area’ defines the portion of a UIViewController’s visible area that is guaranteed to not be obscured by system views, or ancestor views such as UINavigationBar, UITabBar and UIToolbar.

Documentation

systemMinimumLayoutMargins

@property(nonatomic,readonly) NSDirectionalEdgeInsets systemMinimumLayoutMargins API_AVAILABLE(ios(11.0), tvos(11.0)); ```

A new property of type NSDirectionalEdgeInsets that has been added. This property is readonly, and specifies the values of the system layout margins applied to the View Controller. A View Controller’s system layout margins have existed and been managed by UIKit previously, since iOS 8.0, but these values have not been accessible on UIViewController until now. System Layout Margins typically change based on the context (Size Class, Orientation, Hardware Device) that is displaying the View Controller at that time.

Along with the addition of this property, iOS 11.0 introduces the type NSDirectionalEdgeInsets which allows Layout Margins to respect to be aware of and respect Left-To-Right languages as well as Right-To-Left languages. For example, iOS might increase the right-most margin and decrease the left-most margin to cater for an App displaying Right-To-Left content.

Keith Harrison has an excellent post about these changes, if you’d like to know more

Documentation

viewRespectsSystemMinimumLayoutMargins

@property(nonatomic) BOOL viewRespectsSystemMinimumLayoutMargins API_AVAILABLE(ios(11.0), tvos(11.0));

A new BOOL property that has been added. Defaults to YES. This value specifies if the UIViewController respects or ignores the System Minimum Layout Margin (specified using the new systemMinimumLayoutMarginsproperty). Set this value to NO in order to gain full customizability over the UIViewController’s margins by settings the layout margins on the root UIView.

Documentation

viewLayoutMarginsDidChange

- (void)viewLayoutMarginsDidChange NS_REQUIRES_SUPER API_AVAILABLE(ios(11.0), tvos(11.0));

A new method that has been added. This method should be called whenever the layout margins of the UIViewController’s root view have changed. This will cause the View Controller’s content to be updated based on the new margin values.

Documentation

viewSafeAreaInsetsDidChange

- (void)viewSafeAreaInsetsDidChange NS_REQUIRES_SUPER API_AVAILABLE(ios(11.0), tvos(11.0));

A new method that has been added. This method should be called whenever the safe area insets of the UIViewController’s root view have changed. This will cause the View Controller’s content to be updated based on the new safe area insets. Safe Area Insets may be changed when size changes occur on a UINavigationBar, or UIToolbar. This method is always called immediately before the UIViewController appears on screen.

Documentation

Screen Edge Gestures

Changes related to the behavior of system gestures at the screen edges.

preferredScreenEdgesDeferringSystemGestures

- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new property of type UIRectEdge that has been added that defines the screen edges that should take precedence over the system gestures. By default this value is UIRectEdgeNone. By changing this value, an application can define an area in which the application’s gestures take precedence over system defined gestures (such as Swipe to open Control Center, Notification Center or to use Multitasking). If this value is changed, setNeedsUpdateOfScreenEdgesDeferringSystemGestures needs to be called in order to trigger the update.

Documentation

childViewControllerForScreenEdgesDeferringSystemGestures

- (nullable UIViewController *)childViewControllerForScreenEdgesDeferringSystemGestures API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new property added which allows a Container View Controller to specify a Child View Controller to use to calculate the preferredScreenEdgesDeferringSystemGestures value for the visible View. If this value is changed, setNeedsUpdateOfScreenEdgesDeferringSystemGesturesneeds to be called in order to trigger the update.

Documentation

setNeedsUpdateOfScreenEdgesDeferringSystemGestures

- (void)setNeedsUpdateOfScreenEdgesDeferringSystemGestures API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new method added that should be called when the preferredScreenEdgesDeferringSystemGestures value is changed.

Documentation

Home Indicator

Changes related to the iPhone X’s new Home Indicator paradigm.

prefersHomeIndicatorAutoHidden

- (BOOL)prefersHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new BOOL property that has been added that determines whether the system can control when the home indicator is hidden, or if the home indicator is always on when this View Controller is visible.

Documentation

childViewControllerForHomeIndicatorAutoHidden

- (nullable UIViewController *)childViewControllerForHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new property that has been added that allows a Container View Controller to specify a Child View Controller to calculate the prefersHomeIndicatorAutoHidden value for the visible View.

Documentation

setNeedsUpdateOfHomeIndicatorAutoHidden

- (void)setNeedsUpdateOfHomeIndicatorAutoHidden API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);

A new method that has been added that should be called when a View Controller has changed its preference for the prefersHomeIndicatorAutoHidden property.

Documentation

With each year’s release of iOS and the accompanying iPhone/iPad hardware, the frameworks that iOS Engineers use to build their applications need to change in order to support new and improved functionality. Reviewing the API Diffs is a brilliant way of getting your hands dirty and understanding exactly what has changed and why.

If you’ve enjoyed this post, please share it and let me know which Header file you’d like me to explore deeper in the future.