Exploring windows
A window is an instance of the UIWindow
class, and it is the topmost element of any application UI's hierarchy. It doesn't draw any visual object and can be considered as a blank container for the UI elements called views. An application must have at least one window that normally fills the entire screen.
One of the main roles of the window is to deliver touches to the underlying views. You'll read more about this topic in Chapter 7, UI Interactions – Touches and Gestures. For now, it suffices to say that a window is the first entry point for a touch event. The touch is then pushed down through the view hierarchy until it reaches the right view.
The contents of windows
The contents of your applications are mainly directed by view controllers and presented through views, which, in turn, are displayed inside a window. As you will learn in the next section, this sequence is automatically handled by iOS, and all the classes involved in the process are organized to interact seamlessly.
The easiest and most reliable way to send content to a window is by configuring its rootViewController
property with a UIViewController
instance. The view controller's view will automatically be set as the contents of the window and presented to the user.
This solution simplifies the window hierarchy, ensuring that contents are all children of the same root. Thanks to this solution, changing the contents of a window is just a matter of updating its root view controller.
While you'll learn more about view controllers and views in the next paragraphs, this image should clarify how all these objects cooperate to present their contents to the user:
The view controller is initialized and set as the root view controller of the window. Finally, the window presents the current root view controller's view.
Configuring windows
You rarely need to set up a window manually. In most cases, Xcode defines all the needed information for you. Let's take a look at the entire process to better understand what goes on under the hood.
When you create a new Xcode project using the wizard, a Storyboard is created for you. If you check the info.plist
file, you'll see that the Main storyboard filebase name
key reports the name of the Storyboard by default as Main
:
This key is really important as it tells Xcode that you want to start the application from the Storyboard or, more precisely, from the Storyboard initial view controller (the one indicated by the grey arrow inside the Storyboard working area).
The @UIApplicationMain
attribute in the AppDelegate.swift
file is responsible for the launch of the entire application process. It marks an entry point for the application launch, reading the Storyboard's information from the info.plist
file and instantiating the initial view controller.
At this point, a UIWindow
instance is created and associated with the window
property of the AppDelegate
class. This property will be a handy reference to the main window for the entire life cycle of the application.
The initial view controller, previously initialized, is now assigned to the rootViewController
property of the window; therefore, the initial view controller's view becomes the current window's content.
Since windows are invisible by default, there is one last step required to show the content to the user. After the application:didFinishLaunchingWithOptions
function finishes its execution, makeKeyAndVisible
is called for the window, which now loads its interface from rootViewController
and finally displays it contents.
The following image summarizes all these steps:
The same result can be obtained programmatically. If you remove the Main storyboard filebase name
key from the info.plist
file, Xcode doesn't have any information on how to set up a valid window. The application:didiFinishLaunchingWithOptions
function is the right place to manually instantiate it. You can execute the following:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Instantiate a window with the same size of the screen window = UIWindow(frame: UIScreen.mainScreen().bounds) // Instantiate a view controller with the Main storyboard let storyboard = UIStoryboard(name: "Main", bundle: nil) let viewController = storyboard.instantiateViewControllerWithIdentifier("viewController2") as! ViewController // Setup and present the window window?.rootViewController = viewController window?.makeKeyAndVisible() return true }
As you can note, this code retraces the same steps that we saw previously. The only noteworthy thing is the way the window frame is defined: UIScreen
is a class
that represents a screen device. In the previous block of code, the mainScreen
function is used to get the current device bounds and build a window that is the same size as the screen.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.