Core Application Architecture IPHONE APPS

From the time your application is launched by the user, to the time it exits, the UIKit framework manages the majority of the application’s key infrastructure. An iPhone application receives events continuously from the system and must respond to those events. Receiving the events is the job of the UIApplication object but responding to the events is the responsibility of your custom code. In order to understand where you need to respond to events, though, it helps to understand a little about the overall life cycle and event cycles of an iPhone application. The following sections describe these cycles and also provide a summary of some of the key design patterns used throughout the development of iPhone applications.

The Application Life Cycle

The application life cycle constitutes the sequence of events that occurs between the launch and termination of your application. In iPhone OS, the user launches your application by tapping its icon on the Home screen. Shortly after the tap occurs, the system displays some transitional graphics and proceeds to launch your application by calling its mainfunction. From this point on, the bulk of the initialization work is handed over to UIKit, which loads the application’s user interface and readies its event loop. During the event loop, UIKit coordinates the delivery of events to your custom objects and responds to commands issued by your application. When the user performs an action that would cause your application to quit, UIKit notifies your application and begins the termination process.

Figure depicts the simplified life cycle of an iPhone application. This diagram shows the sequence of events that occur from the time the application starts up to the time it quits. At initialization and termination, UIKit sends specific messages to the application delegate object to let it know what is happening. During the event loop, UIKit dispatches events to your application’s custom event handlers. Handling initialization and termination events is discussed later in “Initialization and Termination”, and the event handling process introduced in“The Event-Handling Cycle” and covered in more detail in later chapters.

Application life cycle

The Main Function

In an iPhone application, the main function is used only minimally. Most of the actual work needed to run the application is handled by the UI Application Main function instead. As a result, when you start a new application project in Xcode, every project template provides an implementation of the standard main function like the one in “Handling Critical Application Tasks.” The main routine does only three things: it creates an autorelease pool, it calls UI Application Main, and it releases the autorelease pool. With few exceptions, you should never change the implementation of this function.

The main function of an iPhone application

The UIApplicationMain function at the heart of the preceding listing takes four parameters and uses them to initialize the application. Although you should never have to change the default values passed into this function, it is worth explaining their purpose in terms of starting the application. In addition to the argc and argv parameters passed into main, this function takes two string parameters that identify the principal class (that is, the class of the application object) and the class of the application delegate. If the value of the principal class string is nil, UIKit uses the UIApplication class by default. If the value of the application delegate’s class is nil, UIKit assumes that the application delegate is one of the objects loaded from your application’s main nib file (which is the case for applications built using the Xcode templates). Setting either of these parameters to a non-nil value causes the UI Application Main function to create an instance of the corresponding class during application startup and use it for the indicated purpose. Thus, if your application uses a custom subclass of UI Application (which is not recommended, but certainly possible), you would specify your custom class name in the third parameter.

The Application Delegate

Monitoring the high-level behavior of your application is the responsibility of the application delegate object, which is a custom object that you provide. Delegation is a mechanism used to avoid subclassing complex UIKit objects, such as the default UI Application object.Instead of subclassing and overriding methods, you use the complex object unmodified and put your custom code inside the delegate object. As interesting events occur, the complex object sends messages to your delegate object. You can use these “hooks” to execute your custom code and implement the behavior you need.

The application delegate object is responsible for handling several critical system messages and must be present in every iPhone application. The object can be an instance of any class you like, as long as it adopts the UIApplicationDelegate protocol. The methods of this protocol define the hooks into the application life cycle and are your way of implementing custom behavior. Although you are not required to implement all of the methods, every application delegate should implement the methods described in “Handling Critical Application Tasks”.

The Main Nib File

Another task that occurs at initialization time is the loading of the application’s main nib file. If the application’s information property list (Info.plist) file contains the NS Main Nib File key, the UI Application object loads the nib file specified by that key as part of its initialization process. The main nib file is the only nib file that is loaded for you automatically; however, you can load additional nib files later as needed.

Nib files are disk-based resource files that store a snapshot of one or more objects. The main nib file of an iPhone application typically contains a window object, the application delegate object, and perhaps one or more other key objects for managing the window. Loading a nib file reconstitutes the objects in the nib file, converting each object from its on-disk representation to an actual in-memory version that can be manipulated by your application. Objects loaded from nib files are no different than the objects you create programmatically.

For user interfaces, however, it is often more convenient to create the objects associated with your user interface graphically (using the Interface Builder application) and store them in nib files rather than create them programmatically.

For more information about nib files and their use in iPhone applications, see “Nib Files”. For additional information about how to specify your application’s main nib file, see “The Information Property List”

The Event-Handling Cycle

After the UI Application Main function initializes the application, it starts the infrastructure needed to manage the application’s event and drawing cycle, which is depicted in Figure. As the user interacts with a device, iPhone OS detects touch events and places them in the application’s event queue. The event-handling infrastructure of the UIApplication object takes each event off the top of this queue and delivers it to the object that best suited to handle it. For example, a touch event occurring in a button would be delivered to the corresponding button object. Events can also be delivered to controller objects and other objects indirectly responsible for handling touch events in the application.

The event and drawing cycle

In the iPhone OS Multi-Touch event model, touch data is encapsulated in a single event object (UIEvent). To track individual touches, the event object contains touch objects (UITouch), one for each finger that is touching the screen. As the user places fingers on the screen, moves them around, and finally removes them from the screen, the system reports the changes for each finger in the corresponding touch object.

When it launches an application, the system creates both a process and a single thread for that application. This initial thread becomes the application’s main thread and is where the UI Application object sets up the main run loop and configures the application’ s event-handling code. it shows the relationship of the event-handling code to the main run loop. Touch events sent by the system are queued until they can be processed by the application’s main run loop.

Processing events in the main run loop

The UIApplication object configures the main run loop with an input source that processes touch events by dispatching them to the appropriate responder objects. A responder object is an object that inherits from the UIResponder class and that implements one or more methods for processing the different phases of a touch event. Responder objects in an application include instances of UIApplication, UIWindow, UIView, and all UIView subclasses. The application typically dispatches events to the UIWindow object representing the application’s main window. The window object, in turn, forwards the event to its first responder, which is typically the view object (UIView) on which the touch took place.

In addition to defining the methods you use to handle events, the UIResponder class also defines the programmatic structure of the responder chain, which is the Cocoa mechanism for cooperative event handling. The responder chain is a linked series of responder objects in an application, which usually starts at the first responder. If the first responder object cannot handle the event, it passes it to the next responder in the chain. The message continues traveling up the chain—toward higher-level responder objects such as the window, the application, and the application’s delegate—until the event is handled. If the event isn't handled, it is discarded.

The responder object that handles the event tends to set in motion a series of programmatic actions that result in the application redrawing all or a portion of its user interface (as well as other possible outcomes, such as the playing of a sound). For example, a control object (that is, a subclass of UIControl) handles an event by sending an action message to another object, typically the controller that manages the current set of active views. While processing the action message, the controller might change the user interface or adjust the position of views in ways that require some of those views to redraw themselves. When this happens, the view and graphics infrastructure takes over and processes the required redraw events in the most efficient manner possible.

For more information about events, responders, and how you handle events in your own custom objects, see “Event Handling”. For information about how windows and views fit into the event-handling scheme, see “The View Interaction Model”. For additional information about the graphics infrastructure and how views are updated, see “The View Drawing Cycle”.

Fundamental Design Patterns

The design of the UIKit framework incorporates many of the design patterns found in Cocoa applications in Mac OS X.Understanding these design patterns is crucial to creating iPhone applications, so it is worth taking a few moments to learn about them. The following sections provide a brief overview of these design patterns.