A Window...With Views
An iPhone app displays UI elements and content on the device's screen, and the user responds by tapping the screen or making gestures across it. A singleton window object and multiple views are the visible components that manage the iPhone's UI and any content display. The window object encompasses the entire screen and lacks a border and a title bar with controls. The window and views are implemented by instances of the
UIWindow and various
UIView classes, respectively.
UIWindow class is actually a subclass of
UIView. However, the window instance serves as the root container for all of the other views, and it is always the size of the screen. It serves as a backdrop on which you add any number of views and subviews. The
UIApplication object sends events to the window object, which in turn delivers them to the appropriate view objects.
An iPhone app typically generates an instance of the window object immediately, using information stored in a NextStep Interface Builder (nib) file. Nib files describe the window's dimensions and other information necessary to make an instance of the window. I'll have more to say about nib files later.
Alternatively, you can generate the window instance from code that you write in the delegate. Once the window is set up, you then add the views that make up the app's content and controls as subviews to this window. The
UIView class has methods that allow you to add, remove, or change the order of how views are presented in the window. After you add the app's views, often you are done with the window and deal only with events delivered to the views.
You can see some of how this setup is accomplished in Listing Two. The generation of the window is done for you automatically if you use a nib file, as is the case here. All that you need to do is provide a pointer, termed window in the listing, which references the window instance. Apple's XCode development tools automatically generate the window nib file, MainWindow.xib, along with a
UIApplicationDelegate header file and method file for you.
Views, like the window instance, can be generated either from a nib file or programmatically. The choice of which option to use depends upon how dynamic you intend the view's UI elements to be. For example, a help display with information presented in a static layout is best handled with a nib file. If you have controls that change in response to the user's interaction, you may want to use code to generate a portion of the views and then manage their position and appearance. Likewise, a view with the spaceship needs to move about the screen, so it should be generated by code, and not by a nib.
UIView has a number of child classes that provide useful capabilities (Figure 1). A control group of views implements visual elements such as buttons, sliders, progress indicators, switches, and text labels. Another group serves as containers for dynamic content such as pages or tables. A navigation group provides tab bars and navigation bars that facilitate moving swiftly from one screen of content to another. Other subclasses support scrolling of content, and a toolbar for grouping items.
Views also display content, which might be text, vector graphics, rendered HTML material, or images. For games, you can use cross-platform OpenGL ES APIs to draw and render 3D content, but the OpenGL drawing region must be presented within a view. My program's goals were modest: I only wanted to paint pixels on the screen and move some of them about. The basic
UIView class would be suitable for this purpose.
The origin of a view's coordinate system starts at the upper left corner and the axes extend to the right and downwards; see Figure 2.
Interestingly, for OS X, the situation is reversed: the origin is at the lower left corner and the axes extend to the right and upwards. In fact, the vector graphics APIs, Quartz, still use this orientation in the iPhone, but UIKit automatically corrects the orientation for you before rendering the graphics calls. Coordinates are specified in floating-point numbers for device-resolution independence. A frame describes the view's rectangular area, and its midpoint is defined by an instance of point (a structure with x and y values) termed center. The center point information is handy to have when you move or rotate a view particularly when the view might contain a spaceship image.
Views can be nested in one another, to form complex visual elements, as Figure 2 shows. In addition, views have characteristics known as properties, and the center point is one. Another useful property is alpha, which manages the view's alpha channel. This property can be modified to apply transparency effects to the view's contents. There is also a visibility property, hidden, that can be used to hide or reveal views.
Rotating an image is handled through the view's transform property. This property contains a transformation matrix that can be applied to the view. For me, a transformation that did a simple rotation would be sufficient. However, more complex transformations can be applied to a view's contents, and UIKit provides a number of predefined matrices that can be used to generate special effects with the view's content, or when switching to another view.
At this point, I understood the UIKit framework adequately to know what classes I needed to build the basic core of an iPhone app. This core (an instance of
UIApplicationDelegate) would start by making the required window object, to which I would add a view for a background, and another view that contained the spaceship image. A transformation matrix would rotate the spaceship view. I was a bit fuzzy on the details as how to control the spaceship, but I figured that another view could display a virtual joystick or control pad. That view would then react to touches on it. So far, so good.