Build a view controller in storyboards, configure it with custom views, and fill those views with your app’s data.
Framework
- UIKit
Overview
In the model-view-controller design paradigm, a view controller fits between the view objects that present information onscreen and the data objects that store your app's content. Specifically, a view controller manages a view hierarchy and the state information needed to keep those views up-to-date. Every UIKit app relies heavily on view controllers to present content, and you frequently define custom view controllers to manage your views and UI-related logic.
Most custom view controllers you create are content view controllers—that is, the view controller owns all of its views and manages interactions with those views. Use content view controllers to present your app’s custom content onscreen, and use your view controller object to manage the transfer of data to and from your custom views.

Note
As opposed to a content view controller, a container view controller incorporates content from other view controllers into its view hierarchy. UINavigation
is an example of a container view controller. For information about how to implement a container view controller, see Implementing a Custom Container View Controller.
To define a content view controller, start by subclassing UIView
. If your interface includes a table view or collection view, subclass UITable
or UICollection
instead. New Xcode projects include one or more content view controllers classes for you to modify, and you can add more.
Add Views to Your View Controller
UIView
contains a content view, accessible from the view
property, which serves as the root view of its view hierarchy. To that root view, you add the custom views you need to present your interface. In storyboards, you add views by dragging them onto the view controller scene. For example, the following figure shows a view controller with an image view and button on an iPhone.

After adding views to a view controller, always add Auto Layout constraints to set the size and position of those views. Constraints are rules that specify how to size and position each view relative to its parent or sibling view, and they ensure that your views automatically adapt to different environments and devices. For more information, see View Layout.
Store References to Important Views
At runtime, you may need to access views from your view controller's code. For example, you might want to fetch the text in a text view or change the image in an image view. For that, you need a reference to the view in your view hierarchy. You create those references using outlets.
An outlet is a property in your view controller that includes the IBOutlet keyword. The presence of that keyword tells Xcode to expose that property in your storyboard. The following example code shows the definitions for two outlets. In Swift, include the weak
keyword to prevent your view controller from holding a second strong reference to the view—the first originates from the view hierarchy itself.
@property IBOutlet UIImageView* imageView;
@property IBOutlet UIButton* button;
In your storyboard, connect each outlet to the corresponding view, as described in Add an outlet connection to send a message to a UI object. You do not need to store references to all views in your view hierarchy; store references only to the views you modify later.
When you instantiate a view controller, UIKit reconnects any outlets that you configured in your storyboard. UIKit reestablishes these connections before calling your view controller’s view
method, so you can access the objects in those properties from that method. If you create any views programmatically, you must explicitly assign those views to the appropriate properties of your view controller
Handle Events Occurring in Views and Controls
Controls use the target-action design pattern to report user interactions, and some views post notifications or call delegate methods in response to changes. A view controller needs to know about many of these interactions so it can update its views, and you have several ways to make that happen:
Implement delegate and action methods in your view controller. This option is simple and easy to implement, but it offers less flexiblity and makes it harder to test and validate your code.
Implement delegate and action methods in a class extension on your view controller. This option separates your event-handling code from the rest of your view controller, making it easier to test and validate that code.
Implement delegate and action methods in dedicated objects that then forward relevant information to your view controller. This option offers the most flexibility and reusability. The separation of responsibilities also makes it easier to write unit tests.
To respond to user interactions with controls, define an action method with one of the signatures shown in the following code listing. In your method definition, you may replace the generic reference to UIControl
with a more specific control class.
- (IBAction)doSomething;
- (IBAction)doSomething:(UIControl*)sender;
- (IBAction)doSomething:(UIControl*)sender forEvent:(UIEvent*)event;
For information about the target-action design pattern and how to handle control-related events, see UIControl
.
Prepare Your Views to Appear Onscreen
UIKit gives you several opportunities to configure your view controller and views before displaying them onscreen. When you instantiate your view controller from a storyboard, UIKit creates that object using its init
method.
Note
If your view controller requires custom initialization beyond what a coder object can provide, you can instantiate it programmatically using the instantiate
method of UIStoryboard
. That method lets you create the view controller yourself using a block and a UIKit-provided coder object. This option lets you initialize the view controller with any custom data your view controller requires, and still restore the configuration of views and other objects in the storyboard.
When you present a view controller onscreen, UIKit must first load and configure the corresponding views, which it does using the following sequence of steps:
It creates each view using the view’s
init
method.With Coder: It connects views to the corresponding actions and outlets in the view controller.
It calls the
awake
method of each view and the view controller.From Nib It assigns the view hierarchy to view controller’s
view
property.It calls the view controller’s
view
method.Did Load
At load time, perform only the one-time configuration steps you need to prepare the view controller for use. Use load time to create and configure any additional views that aren't part of your storyboard. Don't perform tasks that must happen each time your view controller appears onscreen. For example, don't start animations or update the values of views.
Perform any final view-related tasks shortly before your views appear onscreen. UIKit notifies the owning view controller when its views are about to appear onscreen, and updates the layout of those views to fit the current environment, by calling the following methods in order:
It updates the view controller's trait collection based on the target window.
It calls the
view
method to let you know the view controller’s view is about to appear onscreen.Will Appear: If needed, it updates the current layout margins and calls the
view
method.Layout Margins Did Change If needed, it updates the safe area insets and calls the
view
method.Safe Area Insets Did Change It calls the
view
method.Will Layout Subviews It updates the layout of the view hierarchy.
It calls the
view
method.Did Layout Subviews It displays the views onscreen.
It calls the view controller’s
view
method.Did Appear:
Update the content of your views in the view
method of your view controller. Changing the content of many views triggers an automatic layout update, so making changes in that method avoids an additional layout step. When making changes, you may use the view controller's trait
property to access information about the current environment, such as the display scale or the vertical and horizontal size classes. Although you can access traits earlier than view
, traits aren't guaranteed to be final until that method. In iOS 12 and earlier, UIKit only provides a partial set of traits at load time, and doesn't provide a complete set of traits until the view
method. For more information about the available traits, see UITrait
.