< Previous PageNext Page >

The Global Application Object

Every Cocoa application is managed by a single NSApplicationobject known by the name of the global variable, NSApp. This singleton instance of NSApplication (or of a custom subclass thereof) has a major responsibility: obtaining user and system events targeted at the application and dispatching them to the appropriate objects. It is also responsible for managing the application's windows, including tracking their current status as key or main window (see “Window Status”).

In this section:

The Main Event Loop
More About Event Dispatch
Window Management
Handling Apple Events


The Main Event Loop

Most of the work that NSApp does takes place in the application's main event loop, which is the basis of the event and drawing cycle. To understand how the main event loop operates, it helps to consider what takes place in a Cocoa application's main entry point. In a standard Xcode Cocoa project, main has a single function call, NSApplicationMain This function does three important things, in the following order:

  1. It obtains the shared application object (NSApp) by invoking the class method sharedApplication.

  2. It loads the application's main nib file into memory.

  3. It runs the application ([NSApp  run]).

Let's examine these steps in a little more detail, starting with some background information. A running application is essentially a process, and each process has a main thread and possibly one or more secondary threads. Each thread always has a run loop created for it; a run loop is a mechanism that monitors sources of input to the process and dispatches control to it when sources become ready for processing.

The main thing that the sharedApplication method does—outside of ensuring a singleton instance—is to set up the programmatic infrastructure for receiving and processing events from the window server. In initializing the global application object, NSApplication establishes a connection to the window server by creating an event source for receiving events (implemented as a Mach port). It also sets up the application's event queue, a FIFO mechanism that enqueues events fetched from the event source as they arrive. Finally, NSApplication initializes the main run loop—the run loop on the main thread—with the event source as an input source (see Figure 6-2.


Figure 6-2  Main event loop, with event source

Main event loop, with event source

The window server receives events from I/O Kit device drivers and dispatches them to the appropriate processes. The process receives the event from the event source in the run loop and places it on a queue.

When the application loads the main nib file, the objects in the file are unarchived along with the connections between these objects. The main nib file always contains the application menu and may contain one or more window objects (with their constituent views). Other nib files may be unarchived at launch time as well; document-based applications, for instance, may unarchive the nib files of documents when a user double-clicks a file in the Finder. This initial graphical user interface is needed so users can begin making requests—by, for instance, choosing a menu item— and consequently generating events for the application to handle.

The NSApplication run method is the workhorse of the main event loop. It first registers Apple event handlers for the application (see “Handling Apple Events”). Then in a closed while loop, run does the following until the application terminates:

  1. It services pending window-display observers on the run loop (see Figure 6-3, which results in the redrawing of regions in windows that are marked as "dirty."


    Figure 6-3  Main event loop, with run-loop observer

    Main event loop, with run-loop observer
  2. It gets the next event in the event queue (nextEventMatchingMask:untilDate:inMode:dequeue:).

  3. It dispatches the event to the object that should next handle it, which in most cases is an NSWindow object (sendEvent:). See “More About Event Dispatch” for clarification.

    Ultimately, numerous objects may become involved in handling the event, and the call stack may grow significantly. After the event is handled, control returns to run.

The funnel point of the main event loop is the nextEventMatchingMask:untilDate:inMode:dequeue: method. If there are events in the event queue, this method fetches the topmost event in the queue and converts the structure to an NSEvent object. If there are no events in the queue, the method blocks. During the period the method blocks, new events from the window server are processed and placed in the queue. The presence of new events "wakes" nextEventMatchingMask:untilDate:inMode:dequeue: and it returns the first matching event in the queue.

If a window has its auto-display feature enabled and it has views marked for display, it also installs an observer (an input source) on the run loop. Just before NSApp processes the next event in the queue, this observer fires, leading to the redrawing of those views. For more on this automatic displaying of window content, see “Windows and Drawing”.

More About Event Dispatch

In its sendEvent: implementation, NSApp looks at the type of event passed in and dispatches it accordingly. Usually the target of the dispatch is one of the application's windows, and the application forwards the event by invoking the sendEvent: method of that NSWindow object. For the two major types of input events, key events and mouse events, NSApp uses a different approach to find the appropriate window.

When users press keys on the keyboard, key events are generated. NSApp forwards these events on to the key window—the window of the application that is currently accepting key presses. (In some cases, such as key equivalents, the application handles NSKeyDown events specially instead of dispatching them.)

When users click an object on a window with a mouse, such as a graphical shape in a drawing program, mouse events are generated. NSApp dispatches mouse events to the window in which the mouse event occurred.

If the object that is clicked or otherwise manipulated is a control object, such as a button or a slider, that object sends an additional sort of message to the application—an action message. That message invokes the sendAction:to:from: method of NSApplication. If a target of the message is not specified, this method searches the responder chains of the application's key and (if necessary) main windows, to find a suitable target. Then it sends the message to the target of the action message.

NSApp deals with other types of events in sendEvent:. Some events are specific to the application itself (such as activation and deactivation), and NSApp handles these itself. Other events are related to one or more windows—for example, a window is exposed or a change is made in screen resolution. For these, NSApp invokes the appropriate method in the affected windows.

Further Reading: The responder chain is described in “Responders and the Responder Chain”. To learn more about key windows, see “Window Status”. For a discussion of NSControl objects and how they work together with NSCell objects, read “Controls and Menus”.

Window Management

Part of the job of the global application object is to manage the windows of the application. NSApp performs the following window-management tasks:

And, as noted in “More About Event Dispatch”, NSApp dispatches window-specific event and action messages to the affected windows. It also maintains the application's Window menu and manages modal windows and panels. (See “Modal Windows” for a description.)

To help it locate windows, the application object keeps a reference to them called its window list (see Figure 6-4). For some window-management tasks (such as deallocation) it iterates through this list. (You can obtain the window list at any time by sending windows to NSApp.) The application object also finds windows by using the window number obtained from the current NSEvent object in a call to windowWithWindowNumber:.


Figure 6-4  The application's window list

The application's window list

Note: NSApp doesn't have anything to do with the layering of windows on the screen (Z -order). That is managed by the window server. For a discussion of window Z-order, see “Window Z-Order and Levels”.

Handling Apple Events

Not all events that an application must deal with come from the event queue. Other processes on a Mac OS X system, such as the Finder and Launch Services, use Apple events to communicate with other processes. They occasionally send an application Apple events to notify it (for example) when users double-click a document in a Finder window or choose Shut Down from the Apple menu, requiring the application to terminate.

When a Cocoa application starts up, one of the first things it does it to register a number of Apple event handlers. When an Apple event is sent to the application, the appropriate handler is invoked. A Cocoa application registers handlers for the following Apple events:

Apple event ID

Description

kAEOpenApplication

Launches an application.

kAEReopenApplication

Reopens an application. It is sent, for example, when an application is running and a user clicks the application icon in the Dock.

kAEOpenDocuments

Provides an application with a list of documents to open. This event is commonly sent when the user selects one or more documents in the Finder and double-clicks them.

kAEPrintDocuments

Provides an application with a list of documents to print. This event is commonly sent when a user selects one or more documents in the Finder and chooses Print from the File menu.

kAEOpenContents

Provides an application with dragged content, such as text or an image. This event is often sent when a user drags a file onto an application’s icon in the Dock.

kAEQuitApplication

Requests the application to terminate.

Note: For more information on this subject, see "How Cocoa Applications Handle Apple Events"



< Previous PageNext Page >


© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-12-20)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.