Understanding Windows and Screens

A window handles the overall presentation of your app’s user interface. Windows work with views (and their owning view controllers) to manage interactions with—and changes to—the visible view hierarchy.

Every app has one window that displays the app’s user interface on an iOS-based device display. If an external display is connected to the device, an app can create a second window to present content on that display as well.

The Role of the Window in an iOS App

In an iOS app, windows play a very different role than do windows in a Mac app. In iOS, windows don’t have title bars, close boxes, or any other visual adornments. Users don’t see, close, or move the window of an iOS app. And instead of opening another window to display new content—which is common behavior in Mac apps—an iOS app changes the views inside its window.

The window object—that is, an instance of UIWindow—has several important responsibilities:

For the most part, you don’t have to do anything to ensure that your app’s window meets these responsibilities. If you use storyboards to create the user interface of your app, the only reason to explicitly create a window object is to support an external device display.

A Window’s Root View Contains Your Content

A window has a single root view controller object that contains all of the other views representing your content. Using a single root view controller simplifies the process of changing your interface, because to display new content, all you have to do is replace the old root view controller with a new one. The easiest way to install a root view into a window is to use storyboards to define your app’s user interface (to learn how storyboards helps you define your UI, see Xcode and Storyboards Can Create, Configure, and Load Your Window).

You can use any view controller you want for a window’s root view controller. Depending on your interface design, the root view controller can be a generic UIViewController object that acts as a container for one or more views, a standard UIKit view controller, or a custom view controller that you define. Some standard UIKit objects commonly used as root view controllers include navigation, tab bar, and split view controllers.

When you set a root view controller, the window adds the root view controller's view to the window and sizes it appropriately. The window uses several factors to determine the correct size for the view—such as the visibility of the status bar, the current device orientation, and whether the view should be displayed full screen.

The Key Window Receives Certain Events

A window is considered the key window when it is currently receiving keyboard and non touch-related events. Whereas touch events are delivered to the window in which the touch occurred, events that don’t have an associated coordinate value are delivered to the key window. Only one window at a time can be key.

Most of the time, the app window becomes the key window. Because iOS uses separate windows to display alert views and input accessory views, these windows can also become key. For example, when an alert or input accessory view has a text field in which the user is currently typing, the window that contains the input view is key.

Most App Windows Exist at the Same Level

When you create a window for your app, the UIWindow class automatically assigns it to what’s called the normal window level, which is the appropriate level to use for windows presenting app-related content. This level, set by the windowLevel property, describes where a window sits on the z-axis relative to other windows. Although you can reconfigure an app-related window to be displayed at some other level, you shouldn’t need to.

In addition to having windows for presenting app-related content, there are also higher-level windows for information that needs to float above the app content. Examples are the system status bar and alerts.

A Window Is Associated with One Device Display

The UIWindow class’s screen property represents the specific device display on which the window is currently displayed. This property contains a screen object—that is, an instance of UIScreen—that contains information about the device display, such as its bounds, mode, and brightness.

The screen object also includes several notifications you can monitor for changes in the device display. For example, you can register for notifications that are sent when a device display is connected or disconnected and when the display’s mode or brightness values change.

Window Notifications Help You Monitor Changes

iOS defines several notifications that indicate changes in window and screen objects. In general, these notifications are most useful for apps that support external displays.

In addition to notifications that indicate when the keyboard is visible (such as UIKeyboardDidShowNotification), UIWindow defines the following notifications:

  • UIWindowDidBecomeVisibleNotification

  • UIWindowDidBecomeHiddenNotification

  • UIWindowDidBecomeKeyNotification

  • UIWindowDidResignKeyNotification

The UIWindow notifications are delivered in response to programmatic changes in your app’s windows. For example, when your app shows or hides a window, the UIWindowDidBecomeVisibleNotification and UIWindowDidBecomeHiddenNotification notifications are delivered accordingly. Note that these notifications are not delivered when your app transitions to the background: Even though the window is not displayed onscreen while your app is in the background, it is still considered visible within the context of your app.

Most apps don’t need to pay attention to the UIWindowDidBecomeVisibleNotification and UIWindowDidBecomeHiddenNotification notifications because it’s rare for an app to have more than one window.

The UIWindowDidBecomeKeyNotification and UIWindowDidResignKeyNotification notifications help you keep track of when your app’s window is key. You might need to know when a window is key if you display an input accessory view to get user input.

Windows and Screens Support a Few Other Tasks

In general, you almost never have to access your app’s window or screen objects unless you need to support an external device display. After app startup—when the window is created, loaded, and configured—there are only a couple of things you might want to do with the window:

  • Use the window object to convert points and rectangles to or from the window’s local coordinate system. For example, if you have a value in window coordinates, you might want to convert it to the coordinate system of a specific view before trying to use it. For information on how to convert coordinates, see Converting Coordinates in the View Hierarchy.

  • Use window notifications to track window-related changes. Windows generate notifications when they are shown or hidden or when they accept or resign the key status. You can use these notifications to perform actions in other parts of your app. For more information, see Window Notifications Help You Monitor Changes.

Similarly, there are only a few reasons you might want to access the screen object. One reason is to adjust the brightness of the host device’s display. For example, you can use the brightness property to give users the ability to set the brightness of their iOS-based device’s display. You can also use the wantsSoftwareDimming property to indicate that your app needs a level of dimness that is lower than the device’s minimum brightness. (Note that turning on wantsSoftwareDimming can have performance implications because the dimness is implemented in software.)

Finally, you might want to use the UIScreen displayLinkWithTarget:selector: method to create a Core Animation display link object that synchronizes your drawing with the display’s refresh rate. To learn more about using a display link object to set up an animation loop, see Rendering Using an Animation Loop. Note that you can use GLKit APIs to set up a display link automatically. To learn more about the GLKit framework, see GLKit Framework Reference.

Xcode and Storyboards Can Create, Configure, and Load Your Window

When you base a new iOS app project on one of the Xcode templates and use storyboards to design your user interface, you don’t have to explicitly create, configure, or load your app’s window.

When you create a main storyboard file for your app—and identify it as the main storyboard in your information property list file—iOS performs several setup tasks for you. Specifically, at launch time iOS:

Before the initial view controller is displayed, your app delegate is called to give you a chance to configure the view controller.

As much as possible, you should use storyboards to specify your app’s user interface (storyboards are not supported on versions of iOS prior to 5.0). If you choose to use nib files instead of storyboards to create your app’s UI, you probably still don’t need to create a window object, because most of the Xcode templates create one for you. (If you do drag a window object into an Interface Builder file, be sure to set its Full Screen at Launch attribute to ensure that the window is sized properly for the target device.)

If you use nib files—instead of storyboards—to create your app’s UI, you need to ensure that the main nib file contents is installed into the window at launch time. To install the main nib file contents into the window you can add to your application:willFinishLaunchingWithOptions: method some code such as the following:

window.rootViewController = myViewController;

In rare cases you might want to create your app’s window programmatically. You would use code something like this to programmatically create a window, install the root view controller, and make the window visible:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   myViewController = [[MyViewController alloc] init];
   window.rootViewController = myViewController;
   [window makeKeyAndVisible];
   return YES;
}