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:
The frame of the window
Whether or not the status bar is visible
Whether or not the status bar is showing additional transient information (such as when a phone call is in progress)
The orientation of the user interface (landscape or portrait)
The value stored in the root view controller’s
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 tab view controller reserves space at the bottom of its view for the tab bar. It sets the currently visible child’s view to use the remainder of the space.
A navigation view controller reserves space at the top for the navigation bar. If the currently visible child wants a navigation bar to be displayed, it also places a view at the bottom of the screen. The remainder of its view is given to the child to fill.
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:
The view controller’s view is resized to the new size.
If autolayout is not in use, the views are resized according to their autoresizing masks.
The view controller’s
viewWillLayoutSubviewsmethod is called.
layoutSubviewsmethod is called. If autolayout is used to configure the view hierarchy, it updates the layout constraints by executing the following steps:
The view controller’s
updateViewConstraintsmethod is called.
UIViewControllerclass’s implementation of the
updateViewConstraintsmethod calls the view’s
After the layout constraints are updated, a new layout is calculated and the views are repositioned.
The view controller’s
viewDidLayoutSubviewsmethod 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:
Use layout constraints to automatically position the views (iOS 6 and later). You override
updateViewConstraintsto add any necessary layout constraints not already configured by the views. Your implementation of this method must call
For more information on layout constraints, see Auto Layout Guide.
Use a combination of autoresizing masks and code to manually position the views (iOS 5.x). You override
layoutSubviewsand use it to reposition any views whose positions cannot be set automatically through the use of resizing masks.
For more information on the autoresizing properties of views and how they affect the view, see View Programming Guide for iOS.