iOS Reference Library Apple Developer
Search

The Core Application Design

Every iOS application is built using the UIKit framework and therefore has essentially the same core architecture. UIKit provides the key objects needed to run the application, to coordinate the handling of user input, and to display content on the screen. Where applications deviate from one another is in how they configure these default objects and also where they incorporate custom objects to augment their application’s user interface and behavior.

There are many interactions that occur between the system and a running application, and many of these interactions are handled automatically by the UIKit infrastructure. However, there are times when your application needs to be aware of the events coming from the system. For example, when the user quits your application, you need to save any relevant data before it goes away. For these situations, UIKit provides hooks that your custom code can use to provide the needed behavior.

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 iOS applications, so it is worth taking a few moments to learn about them. Table 2-1 provides a brief overview of these design patterns.

Table 2-1  Design patterns used by iOS applications

Design pattern

Description

Model-View-Controller

The Model-View-Controller (MVC) design pattern is a way of dividing your code into independent functional areas. The model portion defines your application’s underlying data engine and is responsible for maintaining the integrity of that data. The view portion defines the user interface for your application and has no explicit knowledge of the origin of data displayed in that interface. The controller portion acts as a bridge between the model and view and facilitates updates between them.

Block objects

Block objects are a convenient way to encapsulate code and local stack variables in a form that can be executed later. Support for block objects is available in iOS 4 and later, where they are often used in place of delegates to act as callbacks for asynchronous tasks.

Delegation

The delegation design pattern is a way of modifying complex objects without subclassing them. Instead of subclassing, you use the complex object as is and put any custom code for modifying the behavior of that object inside a separate object, which is referred to as the delegate object. At predefined times, the complex object then calls the methods of the delegate object to give it a chance to run its custom code.

Target-action

Controls use the target-action design pattern to notify your application of user interactions. When the user interacts with a control in a predefined way (such as by tapping a button), the control sends a message (the action) to an object you specify (the target). Upon receiving the action message, the target object can then respond in an appropriate manner (such as by updating application state in response to the button push).

Managed memory model

The Objective-C language uses a reference-counted scheme for determining when to release objects from memory. When an object is first created, it is given a reference count of 1. Other objects can then use the retain, release, or autorelease methods of the object to increase and decrease that reference count appropriately. When an object’s reference count reaches 0, the Objective-C runtime calls the object’s cleanup routines and then deallocates it.

Threads and concurrent programming

All versions of iOS support the creation of operation objects and secondary threads. In iOS 4 and later, applications can also use Grand Central Dispatch (GCD) as the underlying mechanism for executing tasks concurrently. For more information about concurrency and the technologies available for implementing it, see Concurrency Programming Guide.

For a more thorough discussion of these design patterns, see Cocoa Fundamentals Guide.

The Core Application Objects

From the time your application is launched by the user, to the time it exits, the UIKit framework manages most of the application’s key infrastructure. An iOS 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. 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 iOS application. The following sections describe these cycles and also provide a summary of some of the key design patterns used throughout the development of iOS applications.

In addition to showing the UIApplication object, Figure 2-1 shows the objects that are most commonly found in an iOS application, and Table 2-2 describes the roles of each of these types of objects.

Figure 2-1  Key objects in an iOS application

Table 2-2  The role of objects in an iOS application

Object

Description

UIApplicationobject

The UIApplication object manages the application event loop and coordinates other high-level behaviors for your application. You use this object as is, mostly to configure various aspects of your application’s appearance. Your custom application-level code resides in your application delegate object, which works in tandem with this object.

Application delegate object

The application delegate is a custom object that you provide at application launch time, usually by embedding it in your application’s main nib file. The primary job of this object is to initialize the application and present its window onscreen. The UIApplication object also notifies this object when specific application-level events occur, such as when the application needs to be interrupted (because of an incoming message) or suspended (because the user tapped the Home button).

For more information about this object, see “The Application Delegate.”

Data model objects

Data model objects store your application’s content and are therefore custom to your application. For example, a banking application might store information about financial transactions, while a painting application might store an image object or even the sequence of drawing commands that led to the creation of that image. In the latter case, an image object is still a data object because it is just a container for the image data. The actual rendering of that image still takes place elsewhere in your application.

View controller objects

View controller objects manage the presentation of a screen’s worth of content for your application. Typically, this involves loading the views responsible for presenting your content, creating any additional generic controllers to manage portions of the content, and coordinating the interactions with your application’s data model objects.

The UIViewController class is the base class for all view controller objects. It provides default functionality for standard system behaviors such as animating the appearance of views and handling rotations. More specific view controller subclasses provide additional behaviors, such as displaying system-specific screens or interface types.

For detailed information about how to use view controllers, see View Controller Programming Guide for iOS.

UIWindowobject

A UIWindow object manages the drawing surface for your application. Most applications have only one window. An application changes the content of that window by presenting a new set of views using a view controller object.

In addition to hosting views, windows are also responsible for delivering events to those views and to their managing view controllers.

Views, controls, and layers

Views and controls provide the visual representation of your application’s content. A view is an object that draws some content in a designated rectangular area and responds to events within that area. Controls are a specialized type of view responsible for implementing familiar interface objects such as buttons, text fields, and toggle switches.

The UIKit framework provides standard views for presenting many different types of content. You can also define your own custom views by subclassingUIView (or its descendants) directly.

In addition to incorporating views and controls, applications can also incorporate Core Animation layers into their view and control hierarchies. Layer objects are actually data objects that represent visual content. Views use layer objects intensively behind the scenes to render their content. You can also add custom layer objects to your interface to implement complex animations and other types of sophisticated visual effects.

The objects in your application form a complex ecosystem, the specifics of which are what define your application. As you can see from Figure 2-1, most of the objects in an application are either partially or wholly customizable. Fortunately, an application that builds on top of existing UIKit classes receives a significant amount of infrastructure for free. All you have to do is understand the specific points where you can override or augment the default behavior to implement the customizations you need. The remainder of this chapter focuses on the override points that encompass your application’s overall behavior and interactions with the system. It also points you to additional documents where you can find out more about specific types of interactions.

The Application Life Cycle

The application life cycle constitutes the sequence of events that occurs between the launch and termination of your application. In iOS, 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 main function. 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.

Figure 2-2 depicts the simplified life cycle of an iOS application. This diagram shows the sequence of events that occur from the time the application starts up to the time it quits. At key points in the application’s life, UIKit sends 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.

Figure 2-2  Application life cycle

Application life cycle

Prior to iOS 4, only one application at a time was ever allowed to run. As a result, before a new application could be launched, the previous application had to be terminated. This resulted in an application life cycle in which the application was always launched from scratch and then removed from memory at quit time. In iOS 4 and later, applications now remain resident in memory by default after they are quit. This means that subsequent launches of the application may not always involve starting the application from scratch. It also means that you need to design your application code to handle several different state transitions.

The Main Function

Like any C-based application, the main entry point for an iOS application at launch time is the main function. In an iOS application, the main function is used only minimally. Its main job is to hand control off to the UIKit framework. Therefore, any new project you create in Xcode comes with a default main function like the one shown in Listing 2-1. With few exceptions, you should never change the implementation of this function.

Listing 2-1  The main function of an iOS application

#import <UIKit/UIKit.h>
 
int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

Note: An autorelease pool is used in memory management. It is a Cocoa mechanism used to defer the release of objects created during a functional block of code. For more information about autorelease pools, see Memory Management Programming Guide. For specific memory-management guidelines related to autorelease pools in iOS applications, see ‚ÄúAllocate Memory Wisely.‚Äù

The UIApplicationMain function at the heart of your application’s main function 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 creating the application object and creating or loading the application delegate, the UIApplicationMain function also loads the application’s main nib file. All Xcode projects have a main nib file by default, and this file typically contains the application’s window and the application delegate object. UIKit obtains the name of the main nib file by looking at the value in the NSMainNibFile key in your application’s Info.plist file. Although you should rarely need to do so, you can designate a new main nib file for your application by changing the value of this key before building your project. For more information about the Info.plist file and how you use it to configure your application, see “The Information Property List.”

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 UIApplication 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.

Important: The delegate design pattern is intended to save you time and effort when creating applications and is therefore a very important pattern to understand. For an overview of the key design patterns used by iOS applications, see ‚ÄúFundamental Design Patterns.‚Äù For a more detailed description of delegation and other UIKit design patterns, see Cocoa Fundamentals Guide.

The application delegate object is responsible for handling several critical system messages and must be present in every iOS 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 Figure 7-2.

For additional information about the methods of the UIApplicationDelegate protocol, see UIApplicationDelegate Protocol Reference.

Understanding an Application’s States and Transitions

Applications running in iOS 4 and later can be in one of several different states at any given time. Table 2-3 lists the potential runtime states of an application in iOS 4 and later.

Table 2-3  Application states

State

Description

Not running

The application has not been launched or was running but was terminated by the system.

Inactive

The application is running in the foreground but is currently not receiving events. (It may be executing other code though.) An application never stays in this state for very long. It almost always enters this state on its way to somewhere else. The only time it stays inactive for any period of time is when the system must prompt the user to respond to some event, such as an incoming phone call or SMS message.

Active

The application is running in the foreground and is receiving events.

Background

The application is in the background and executing code. Most applications enter this state briefly on their way to being suspended. However, an application that requests extra execution time may remain in this state for a period of time. In addition, an application being launched directly into the background enters this state instead of the inactive state. For information about how to execute code while in the background, see “Executing Code in the Background.”

The background state is only available in iOS 4 and later and on devices that support multitasking. If this state is not available, applications are terminated and moved to the not running state instead.

Suspended

The application is in the background but is not executing code. The system moves application to this state automatically and at appropriate times. While suspended, an application is essentially freeze-dried in its current state and does not execute any code. During low-memory conditions, the system purges suspended applications without notice to make more space for the foreground application.

The suspended state is only available in iOS 4 and later and on devices that support multitasking. If this state is not available, applications are terminated and moved to the not running state instead.

The following sections describe the key state transitions in more detail and call out the typical behaviors your application should observe during the transition.

Launching the Application

At launch time, an application moves from the not running state to either the active or the background state. A launching application has to prepare itself to run and then check to see if the system has launched it in order to perform a specific task. During the initial startup sequence, the application calls its delegate’s application:didFinishLaunchingWithOptions: method followed by either the applicationDidBecomeActive: or applicationDidEnterBackground: method (depending on whether it is transitioning to the foreground or background).

Note: Launching into the background state does not occur in iOS 3.x and earlier or on devices that do not support multitasking. Applications in those circumstances launch only into the active state.

Figure 2-3 shows the sequence of steps that occur when launching into the foreground. The sequence for launching into the background is the same except that the applicationDidBecomeActive: method is replaced by the applicationDidEnterBackground: method.

Figure 2-3  Launching into the active state

The application delegate’s application:didFinishLaunchingWithOptions: method is responsible for doing most of the work at launch time and has the following responsibilities:

You should strive to make your application:didFinishLaunchingWithOptions: method as lightweight as possible. Although there are any number of custom initialization tasks you could perform in this method, if this method takes too long to complete those tasks, the system might terminate the application for being unresponsive. One way to make the method lightweight is to initiate tasks asynchronously or move any long-running tasks to secondary threads. This is especially important for network-based operations that could take an indeterminate amount of time to complete.

When your application:didFinishLaunchingWithOptions: method is called, the applicationState property of the UIApplication object is already set to the appropriate state for your application. If the property is set to UIApplicationStateInactive, your application is in the inactive state and is about to be moved to the foreground. If it is set to UIApplicationStateBackground, the application is about to be moved to the background. In either case, you can use this information to prepare your application appropriate for running.

Applications are launched into the background only as needed to handle an incoming background event. When launched into the background, an application generally has a limited amount of execution time and should therefore avoid doing work that is not immediately relevant to processing the background event. For example, you should avoid setting up your application’s user interface. Instead, you should make a note that the interface needs to be configured and do that work when moving to the foreground later. For additional guidance about how to configure your application for background execution, see “Being a Responsible, Multitasking-Aware Application.”

Moving to the Background

When the user presses the Home button or the system launches another application, the foreground application transitions first to the inactive state and then to the background state. This results in calls to the application delegate’s applicationWillResignActive: and applicationDidEnterBackground: methods, as shown in Figure 2-4. Most background applications move to the suspended state shortly after returning from the applicationDidEnterBackground: method. If your application requests more execution time or declares itself to support background execution, it is allowed to continue running after this method returns.

Figure 2-4  Moving from the foreground to the background

When your delegate’s applicationDidEnterBackground: is called, your application has approximately five seconds to finish any lingering tasks and return. If the method does not return before time runs out (or request more execution time from the system), your application is terminated and purged from memory.

The UIApplicationDidEnterBackgroundNotification notification is also sent to notify interested parts of your application that it is entering the background. Objects in your application can use the default notification center to register for this notification.

You should use the applicationDidEnterBackground: method to save user data and any state information needed to restore your application in the event that it is subsequently purged from memory. When an application enters the background state, there is no guarantee that it will remain there indefinitely. If the device’s memory continues to be constrained, the system purges background applications to make more room. If your application is suspended when that happens, it receives no notice that it is removed from memory. Thus, you need to save any data beforehand.

Important: All multitasking-aware applications should behave responsibly when moving to the background. This is true regardless of whether your application is suspended shortly after entering the background or continues running. Saving the user‚Äôs data is one step that should always be taken, but there other guidelines that you should follow. For a list of these guidelines, see ‚ÄúBeing a Responsible, Multitasking-Aware Application.‚Äù

When an application moves to the background, all of your core application objects remain in memory and are available for use while in the background. These objects include your custom objects and data structures plus your application’s controller objects, windows, and views. However, the system does release many of the objects used behind-the-scenes to support your application. Specifically, the system does the following for background applications:

If the application is running in iOS 3.x and earlier or on a device that does not support multitasking, the application is terminated instead of being moved to the background. For more information about how to respond to the termination of your application, see “Responding to Application Termination.”

Responding to Interruptions

When the application is interrupted by an incoming phone call, SMS, or calendar notification, the application moves to the inactive state temporarily. It remains in this state until the user decides whether to accept or ignore the interruption. If the user ignores the interruption, the application is reactivated, at which time it can resume any services it stopped when it moved into the inactive state. If the user accepts the interruption, the application moves into the suspended state. Figure 2-5 shows the set of steps this process follows. The steps that follow describe this process in more detail.

Figure 2-5  Handling application interruptions

  1. The system detects an incoming phone call or SMS message, or a calendar event occurs.

  2. The system calls your application delegate’sapplicationWillResignActive: method. The system also disables the delivery of touch events to your application.

    Interruptions amount to a temporary loss of control by your application. If such a loss of control might affect your application’s behavior or cause a negative user experience, you should take appropriate steps in your delegate method to prevent that from happening. For example, if your application is a game, you should pause the game. You should also disable timers, throttle back your OpenGL frame rates (if using OpenGL), and generally put your application into a sleep state. While your application is in the inactive state, it continues to run but should not do any significant work.

  3. The system displays an alert panel with information about the event. The user can choose to ignore the event or respond to it.

  4. If the user ignores the event, the system calls your application delegate’s applicationDidBecomeActive: method and resumes the delivery of touch events to your application.

    You can use this delegate method to reenable timers, throttle up your OpenGL frame rates, and generally wake up your application from its sleep state. For games that are in a paused state, you should consider leaving the game in that state until the user is ready to resume play. For example, you might display an alert panel with controls to resume play.

  5. If the user responds to the event instead of ignoring it, the system calls your application delegate’s applicationDidEnterBackground: method. Your application should move to the background as usual, saving any user data or contextual information needed to restore your application to its current state later.

    If the application is running in iOS 3.x or earlier or on a device that does not support multitasking, the application delegate’s applicationWillTerminate: method is called instead of the applicationDidEnterBackground: method.

Depending on what the user does while responding to an interruption, the system may return to your application when that interruption ends. For example, if the user takes a phone call and then hangs up, the system relaunches your application. If, while on the call, the user goes back to the Home screen or launches another application, the system does not return to your application.

Important: When the user takes a call and then returns to your application while on the call, the height of the status bar grows to reflect the fact that the user is on a call. Similarly, when the user ends the call, the status bar height shrinks back to its regular size. Your application should be prepared for these changes in the status bar height and adjust its content area accordingly. View controllers handle this behavior for you automatically. If you lay out your user interface programmatically, however, you need to take the status bar height into account when laying out your views and implement the layoutSubviews method to handle dynamic layout changes.

If the user presses the Sleep/Wake button on a device while running your application, the system calls your application delegate’s applicationWillResignActive: method, stops the delivery of touch events, and then puts the device to sleep. When the user wakes the device later, the system calls your application delegate’s applicationDidBecomeActive: method and begins delivering events to the application again. While the device is asleep, foreground and background applications continue to run, but those applications should do as little work as possible in order to preserve battery life.

Resuming Foreground Execution

When the user launches an application that currently resides in the background, the system moves it to the inactive state and then to the active state. This results in calls to the applicationWillEnterForeground: and applicationDidBecomeActive: methods of the application delegate, as shown in Figure 2-6.

Figure 2-6  Transitioning from the background to the foreground

When moving to the foreground, your application should restart any services it stopped and generally prepare itself for handling events again.

Note: The UIApplicationWillEnterForegroundNotification notification is also available for tracking when your application reenters the foreground. Objects in your application can use the default notification center to register for this notification.

While an application is suspended, the system tracks and coalesces events that might have an impact on that application when it relaunches. As soon as your application is up and running again, the system delivers those events to it. For most of these events, your application’s existing infrastructure should just respond appropriately. For example, if the device orientation changed, your application’s view controllers would automatically update the interface orientation in an appropriate way. For more information about the types of events that are tracked by the system while your application is in the background, and the appropriate way to handle those events, see “Responding to System Changes While in the Background.”

Responding to Application Termination

Although applications are generally moved to the background and suspended, if any of the following conditions are true, your application is terminated and purged from memory instead of being moved to the background:

If your application is running (either in the foreground or background) at termination time, the system calls your application delegate’s applicationWillTerminate: method so that you can perform any required cleanup. You can use this method to save user data or application state information that you would use to restore your application to its current state on a subsequent launch. Your method implementation has approximately five seconds to perform any tasks and return. If it does not return in time, the application is forcibly terminated and removed from memory. The applicationWillTerminate: method is not called if your application is currently suspended.

Even if you develop your application using iPhone SDK 4 and later, you must still be prepared for your application to be terminated. The user can terminate applications explicitly using the multitasking UI. In addition, if memory becomes constrained, the system might remove applications from memory in order to make more room. If your application is currently suspended, the system removes your application from memory without any notice. However, if your application is currently running in the background state (in other words, not suspended), the system calls the applicationWillTerminate: method of your application delegate. Your application cannot request additional background execution time from this method.

Multitasking

In iOS 4 and later, multiple applications may reside in memory and run simultaneously. Only one application runs in the foreground while all other applications reside in the background. Applications running in this environment must be designed to handle transitions between the foreground and background.

Checklist for Supporting Multitasking

Applications that support multitasking in iOS 4 and later should do the following:

If you do not want to support multitasking at all, you can opt out and elect to always have your application terminated and purged from memory at quit time. For information on how to do this, see “Opting Out of Background Execution.”

Responding to System Changes While in the Background

While an application is in the suspended state, it does not receive system-related events that might be of interest. However, the most relevant events are captured by the system and queued for later delivery to your application. To prevent your application from becoming overloaded with notifications when it resumes, the system coalesces events and delivers a single event (of each relevant type) corresponding to the net change since your application was suspended.

To understand how this might work in your application, consider an example. Suppose that at the time when your application is suspended, the device is in a portrait orientation. While the application is suspended, the user rotates the device to landscape left, upside down, and finally landscape right orientations before launching your application again. Upon resumption, your application would receive a single device orientation event indicating that the device changed to a landscape-right orientation. Of course, if your application uses view controllers, the orientation of those view controllers would be updated automatically by UIKit. Your application would need to respond only if it tracked device orientation changes explicitly.

Table 2-4 lists the events that are coalesced and delivered to your application. In most cases, the events are delivered in the form of a notification object. However, some events may be intercepted by a system framework and delivered to your application by another means. Unless otherwise noted, all events are delivered regardless of whether your application resumes in the foreground or background.

Table 2-4  Notifications delivered to waking applications

Event

Notification mechanism

Your code marks a view as dirty

Any calls to setNeedsDisplay or setNeedsDisplayInRect: on one of your views are coalesced and stored until your application resumes in the foreground. These events are not delivered to applications running in the background.

An accessory is connected or disconnected

EAAccessoryDidConnectNotification

EAAccessoryDidDisconnectNotification

The device orientation changes

UIDeviceOrientationDidChangeNotification

In addition to this notification, view controllers update their interface orientations automatically.

There is a significant time change

UIApplicationSignificantTimeChangeNotification

The battery level or battery state changes

UIDeviceBatteryLevelDidChangeNotification

UIDeviceBatteryStateDidChangeNotification

The proximity state changes

UIDeviceProximityStateDidChangeNotification

The status of protected files changes

UIApplicationProtectedDataWillBecomeUnavailable

UIApplicationProtectedDataDidBecomeAvailable

An external display is connected or disconnected

UIScreenDidConnectNotification

UIScreenDidDisconnectNotification

The screen mode of a display changes

UIScreenModeDidChangeNotification

Preferences that your application exposes through the Settings application are changed

NSUserDefaultsDidChangeNotification

The current language or locale settings changes

NSCurrentLocaleDidChangeNotification

When your application resumes, any queued events are delivered via your application’s main run loop. Because these events are queued right away, they are typically delivered before any touch events or other user input. Most applications should be able to handle these events quickly enough that they would not cause any noticeable lag when resumed. However, if your application appears sluggish in responding to user input when it is woken up, you might want to analyze your application using Instruments and see if your handler code is causing the delay.

Handling Locale Changes Gracefully

If the user changes the language or locale of the device while your application is suspended, the system notifies you of that change using the NSCurrentLocaleDidChangeNotification notification. You can use this notification to force updates to any views containing locale-sensitive information, such as dates, times, and numbers. Of course, you should also be careful to write your code in ways that might make it easy to update things easily:

Responding to Changes in Your Application’s Settings

If your application has settings that are managed by the Settings application, it should observe the NSUserDefaultsDidChangeNotification notification. Because the user can modify settings while your application is in the background, you can use this notification to respond to any important changes in those settings. For example, an email program would need to respond to changes in the user’s mail account information. Failure to do so could have serious privacy and security implications. Specifically, the user might still be able to send email using the old account information, even if the account did not belong to that person.

Upon receiving the NSUserDefaultsDidChangeNotification notification, your application should reload any relevant settings and, if necessary, reset its user interface appropriately. In cases where passwords or other security-related information has changed, you should also hide any previously displayed information and force the user to enter the new password.

Opting Out of Background Execution

If you do not want your application to remain in the background when it is quit, you can explicitly opt out of the background execution model by adding the UIApplicationExitsOnSuspend key to your application’s Info.plist file and setting its value to YES. When an application opts out, it cycles between the not running, inactive, and active states and never enters the background or suspended states. When the user taps the Home button to quit the application, the applicationWillTerminate: method of the application delegate is called and the application has approximately five seconds to clean up and exit before it is terminated and moved back to the not running state.

Opting out of background execution is strongly discouraged but may be preferable under certain conditions. Specifically, if coding for the background requires adding significant complexity to your application, terminating the application may be a simpler solution. Also, if your application consumes a large amount of memory and cannot easily release any of it, the system might need to terminate your application quickly anyway to make room for other applications. Thus, opting to terminate, instead of switching to the background, might yield the same results and save you development time and effort.

Note: Explicitly opting out of background execution is necessary only if your application is linked against iPhone SDK 4 and later. Applications linked against earlier versions of the SDK do not support background execution as a rule and therefore do not need to opt out explicitly.

For more information about the keys you can include in your application’s Info.plist file, see Information Property List Key Reference.

Windows, Views, and View Controllers

You use windows and views to present your application’s visual content on the screen and to manage the immediate interactions with that content. A window is an instance of the UIWindow class. All iOS applications have at least one window, and some applications may have additional windows to manage specific types of content. An application’s main window fills the entire main screen and has no visual adornments such as a title bar or close box. A window is simply a blank canvas that you use to host one or more views. Therefore, all manipulations to windows must occur through the programmatic interfaces of the UIWindow class.

A view, an instance of the UIView class, defines a rectangular region inside a window. Views are the primary mechanism for interacting with the user in your application. Views have several responsibilities in your application, including:

View controllers play an important part of your application’s overall design and structure. Applications running on iOS-based devices have a limited amount of screen space in which to display content. To better manage that screen space, an application uses view controller objects to coordinate the presentation of self-contained view hierarchies. When you want to make significant changes to your application’s content, rather than change the underlying view objects manually, which is tedious and error prone, you simply present the contents of a new view controller. View controller objects are descendants of the UIViewController class, which is defined in the UIKit framework.

Each view controller object can be thought of as an island unto itself. It manages the presentation of its views, handles their creation and destruction, and facilitates the interactions between those views and other objects in your application. The view controller manages a single top-level view directly and may manage all or some of that view’s subviews. For simple user interfaces, a view controller typically manages all of the views in its view hierarchy. However, for more complex interfaces comprised of several distinct pieces, a view controller may manage a subset of views and rely on one or more custom controller objects to manage other groups of views in the view hierarchy.

Understanding view controllers, and the infrastructure they provide, is important to developing iOS applications. For more information about this infrastructure and how you use view controllers to manage your application’s user interface, see View Controller Programming Guide for iOS. For more information about implementing windows and views, see View Programming Guide for iOS.

The Event-Handling System

The iOS event-handling system is responsible for tracking touch and motion events and delivering them to your application. All events are delivered to the application through the UIApplication object, which manages the queue of incoming events and distributes them to other parts of the application. For most applications, touches are the most significant type of event you can receive. Other types of events may also be generated and delivered, but touches reflect direct interactions with your application’s views.

When it launches an application, the system creates both a process and a single thread for the application. This initial thread becomes the application’s main thread. This is where the UIApplication object sets up the main run loop and configures its event-handling code, as shown in Figure 2-7. As touch events come into the application, they are queued until the application is ready to process them. The application processes events in the main run loop to ensure that they are handled sequentially as they arrive. The actual handling of a given event usually occurs in other objects, such as your application’s views and view controllers.

Figure 2-7  Processing events in the main run loop

Processing events in the main run loop

Note: A run loop monitors sources of input for a given thread of execution. The application‚Äôs event queue represents one of these input sources. When an event arrives, the run loop wakes up the thread and dispatches control to the handler for the event queue, which in this case is the UIApplication object. When the handler finishes, control passes back to the run loop, which then processes another event, processes other input sources, or puts the thread to sleep if there is nothing more to do. For more information about how run loops and input sources work, see Threading Programming Guide.

Every event sent to an application is encapsulated in a single event object (UIEvent). In the case of touch-related events, the event object contains one or more touch objects (UITouch) representing the fingers that are 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.

Distributing and handling events is the job of responder objects, which are instances of the UIResponder class. The UIApplication, UIViewController, UIWindow, and UIView classes are all descendants of UIResponder. After pulling an event off the event queue, the application dispatches that event to the UIWindow object where it occurred. The window object, in turn, forwards the event to its first responder. In the case of touch events, the first responder is typically the view object (UIView) in which the touch took place. For example, a touch event occurring in a button is delivered to the corresponding button object.

If the first responder is unable to handle an event, it forwards the event to its next responder, which is typically a parent view or view controller. If that object is unable to handle the event, it forwards it to its next responder, and so on until the event is handled. This series of linked responder objects is known as the responder chain. Messages continue traveling up the responder 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 an event tends to set in motion a series of programmatic actions by the application. 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 Guide for iOS.

The Graphics and Drawing System

There are two basic drawing paths an application can follow in iOS:

The native drawing technologies rely on the infrastructure provided by views and windows to render and present custom content. When a view is first shown, the system asks it to draw its content. System views draw their contents automatically, but for custom views, the system calls the drawRect: method of the view. Inside this method, you use the native drawing technologies to draw shapes, text, images, gradients, or any other visual content you want. When you want to change the contents of the view, you do not call the drawRect: method yourself. Instead, you ask the system to redraw all or part of the view by calling the setNeedsDisplay or setNeedsDisplayInRect: method. This cycle then repeats and continues throughout the lifetime of your application.

If you are using OpenGL ES to draw your application’s content, you still create a window and view to manage your content but you use them in a different way. Instead of the view drawing your application’s content, the view simply provides the rendering surface that you then use to create an OpenGL drawing context. You then use that context and your own timing information to coordinate updates to your application’s content.

For information about how to use views and the native rendering technologies to draw your application’s content, see View Programming Guide for iOS. For detailed information about how to use OpenGL ES to draw your application’s content, see OpenGL ES Programming Guide for iOS.

The Text System

The text system in iOS provides everything you need to receive input from the user and display the resulting text in your application. On the input side, the system handles text input occurs through the system keyboard, which is tied to the first responder object. Although it is referred to as the keyboard, its appearance does not always look like a traditional keyboard. Different languages have different text input requirements, and so the keyboard adapts as needed to support different input methods. Figure 2-8 shows several different variants of the system keyboard that are presented automatically based on the user’s current language settings.

Figure 2-8  Several different keyboards and input methods

For displaying text, applications have a variety of options. For simple text display and editing, you can use UIKit classes such as UILabel, UITextField, and UITextView. You can also do simple text display using special additions to the NSString class provided by UIKit. For more sophisticated layout, you can use the Core Graphics text facilities or Core Text. Both frameworks provide drawing primitives to render strings of text. In addition, the Core Text framework provides a sophisticated layout engine for computing line positions, text runs, and page layout information that you can then use when drawing the text.

For information about how to support text input and rendering in your application, see Text and Web Programming Guide for iOS.

Audio and Video Support

Whether multimedia features are central or incidental to your application, iOS users expect high quality. When presenting video content, take advantage of the device’s high-resolution screen and high frame rates. When designing the audio portion of your application, keep in mind that compelling sound adds immeasurably to a user’s overall experience.

You can use the iOS multimedia frameworks to add features like:

For more information about the audio and video technologies available in iOS, see iOS Technology Overview. For information about how to use the audio and video technologies in iOS, see Multimedia Programming Guide.

Integration with the Hardware and System Applications

An iOS application does not need to be isolated from the rest of the system. In fact, the best applications take advantage of both hardware and software features on the device to provide a more intimate experience for the user. Devices contain a lot of user-specific information, much of which is accessible through the system frameworks and technologies. Table 2-5 lists a few of the features you can incorporate into your applications.

Table 2-5  System integration technologies

Integration with…

Description

The user’s contacts

Applications that need access to the user’s contacts can use the Address Book framework to access that information. You can also use the Address Book UI framework to present standard system interfaces for picking and creating contacts. For more information, see Address Book Programming Guide for iOS.

Systemwide calendar and time-based events

Applications that need to schedule time-based events can use the Event Kit and Event Kit UI frameworks to do so. Events scheduled using this framework show up in the Calendar application and other applications that support this framework.

The Mail and Messages applications

If your application sends email or SMS messages, you can use the view controllers in the Message UI framework to present the standard system interfaces for composing and sending those messages.

Telephony information

Applications that need information about the telephony features of a device can access that information using the Core Telephony framework. For example, a VoIP application might use this capability to detect an in-progress cellular call and handle VoIP calls differently.

The camera hardware and the user’s photo library

Applications that need access to the camera or the user’s photo library can access them both using the UIImagePickerController class. This class presents a standard system interface for retrieving images from the user.

Unknown file types

If your application interacts with unknown file types, you can use the UIDocumentInteractionController class to preview the contents of the files or find an application cable of opening them. Email applications and other network-based applications are typical candidates for interacting with unknown file types.

Pasteboard data

The pasteboard is a way of moving information around inside an application but is also a way to share information with other applications. Data on the pasteboard can be copied into other applications and incorporated.

The location of the device

Applications can take advantage of location-based data to tailor the content presented to the user. For example, searches for local restaurants or services can be limited to nearby places only. Location services are also used frequently to create social connections by showing the location of nearby users.

For information about using Core Location, see Location Awareness Programming Guide.

Map information

Applications can incorporate maps into their applications and layer information on top of those maps using the Map Kit framework. For information about using Map Kit, see Location Awareness Programming Guide.

External hardware accessories

Developers can create software that interacts with connected external hardware using the External Accessory framework. For information about communicating with external accessories, see External Accessory Programming Topics.

For a complete list of technologies you can incorporate into your applications, see iOS Technology Overview.




Last updated: 2010-06-30

Did this document help you? Yes It's good, but... Not helpful...