Resizing the View Controller’s Views

A view controller owns its own view and manages the view’s contents. In the process, the view controller also manages the view’s subviews. But in most cases, the view’s frame is not set directly by the view controller. Instead, the view’s frame is determined by how the view controller’s view is displayed. More directly, it is configured by the object used to display it. Other conditions in the app, such as the presence of the status bar, can also cause the frame to change. Because of this, your view controller should be prepared to adjust the contents of its view when the view’s frame changes.

A Window Sets the Frame of Its Root View Controller’s View

The view associated with the window’s root view controller gets a frame based on the characteristics of the window. The frame set by the window can change based on a number of factors:

If your app displays the status bar, the view shrinks so that it does not underlap the status bar. After all, if the status bar is opaque, there is no way to see or interact with the content lying underneath it. However, if your app displays a translucent status bar, you can set the value of your view controller’s wantsFullScreenLayout property to YES to allow your view to be displayed full screen. The status bar is drawn over the top of the view.

Full screen is useful when you want to maximize the amount of space available for displaying your content. When displaying content under the status bar, place that content inside a scroll view so that the user can scroll it out from under the status bar. Being able to scroll your content is important because the user cannot interact with content that is positioned behind the status bar or any other translucent views (such as translucent navigation bars and toolbars). Navigation bars automatically add a scroll content inset to your scroll view (assuming it is the root view of your view controller) to account for the height of the navigation bar; otherwise, you must manually modify the contentInset property of your scroll view.

A Container Sets the Frames of Its Children’s Views

When a view controller is a child of a container view controller, its parent decides which children are visible. When it wants to show the view, it adds it as a subview in its own view hierarchy and sets its frame to fit it into its user interface. For example:

A child gets its frame from the parent all the way up to the root view controller, which gets its frame from the window.

A Presented View Controller Uses a Presentation Context

When a view controller is presented by another view controller, the frame it receives is based on the presentation context used to display the view controller. See “Presentation Contexts Provide the Area Covered by the Presented View Controller.”

A Popover Controller Sets the Size of the Displayed View

A view controller displayed by a popover controller can determine the size of its view’s area by setting its own contentSizeForViewInPopover property value to the size it wants. If the popover controller sets its own popoverContentSize property to a different view size, its size value overrides the view controller’s setting. To match the model used by other view controllers, use the popover controller’s properties to control its size and position.

How View Controllers Participate in the View Layout Process

When the size of a view controller’s view changes, its subviews are repositioned to fit the new space available to them. The views in the controller’s view hierarchy perform most of this work themselves through the use of layout constraints and autoresizing masks. However, the view controller is also called at various points so that it can participate in the process. Here’s what happens:

  1. The view controller’s view is resized to the new size.

  2. If autolayout is not in use, the views are resized according to their autoresizing masks.

  3. The view controller’s viewWillLayoutSubviews method is called.

  4. The view’s layoutSubviews method is called. If autolayout is used to configure the view hierarchy, it updates the layout constraints by executing the following steps:

    1. The view controller’s updateViewConstraints method is called.

    2. The UIViewController class’s implementation of the updateViewConstraints method calls the view’s updateConstraints method.

    3. After the layout constraints are updated, a new layout is calculated and the views are repositioned.

  5. The view controller’s viewDidLayoutSubviews method is called.

Ideally, the views themselves perform all of the necessary work to reposition themselves, without requiring the view controller to participate in the process at all. Often, you can configure the layout entirely within Interface Builder. However, if the view controller adds and removes views dynamically, a static layout in Interface Builder may not be possible. In this case, the view controller is a good place to control the process, because often the views themselves only have a limited picture of the other views in the scene. Here are the best approaches to this in your view controller: