The Window
The top of the view hierarchy is the app’s window. It is an instance of UIWindow (or your own subclass thereof), which is a UIView subclass. Your app should have exactly one main window. It occupies the entire screen and forms the background to, and the ultimate superview of, all your other visible views. Other views are visible by virtue of being subviews, at some depth, of your app’s window. (If your app can display views on an external screen, you’ll create an additional UIWindow to contain those views; but in this chapter I’ll behave as if there were just one screen, the device’s own screen,and just one window.)
The project templates all generate your app’s window for you automatically. The window is a top-level nib object in the project’s main nib file. This nib file is loaded automatically as the app launches, and the window is instantiated. Another top-level nib object in the main nib file, representing the app delegate, has a window outlet pointing to the window. The app delegate instance, which is also generated as the app launches, thus points to the window through its window property. (It also retains the window, but it need not do so, as the window is also being retained by the UIApplication instance,
the nib’s owner.) The app delegate instance is sent the application:didFinishLaunchingWithOptions: delegate message by the application instance, and in turn it sends the window instance the makeKeyAndVisible message. This causes the window to appear and gives your app a visible manifestation.
In theory, you could modify this process and generate your app’s UIWindow in some other way. For example, you could generate the UIWindow instance in code. Apple says to do this by saying:
UIWindow* aWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
By virtue of the project templates, the app delegate points to the window as the value of its window property; so any code in the app delegate class can refer to the window as self.window. Code elsewhere can also get a reference to the app’s window; here, I do it by way of the synthesized accessor:
UIWindow* theWindow = [[[UIApplication sharedApplication] delegate] window];
That code is unusual, though, and may require typecasting to quiet the compiler (because the class of the application’s delegate property is otherwise unknown). You’d be more likely to use the application’s keyWindow property:
UIWindow* theWindow = [[UIApplication sharedApplication] keyWindow];
An even more likely way to get a reference to your app’s window would be through a subview of the window, at any depth of the hierarchy. You are very likely to have a reference to at least one such subview, and its window property points to the window that contains it, which is the app’s window. You can also use a UIView’s window property as a way of asking whether it is ultimately embedded in a window; if it isn’t, its window property is nil. A UIView whose window property is nil cannot be visible to the user.
Although your app will have exactly one primary window, it may generate other windows of which you are not conscious. For example, if you put up an alert view (UIAlertView), it is displayed in a secondary window that lies on top of your app’s window; at that moment, this secondary window is the application’s keyWindow. You would not be conscious of this fact, however, unless you needed a reference to your app’s window while an alert was showing, which is unlikely.