2.11. Application EnvironmentsMost of the typical application development occurs in the Application Environments layer. Mac OS X has multiple application environments, each providing features that may appeal to certain types of developers. For example, those interested in programming using "plain old" Unix APIs are equally well served on Mac OS X as those who wish to use visual tools for rapid prototyping, creation of complex graphical user interfaces, and object-oriented development. Of the vast number of portable programming language implementations in existence, many are readily accessible on Mac OS X, and some are bundled by Apple. In particular, Apple's own programming environment offers rich APIs for Mac OS Xspecific development. Although it would be impractical to enumerate all types of applications that can run on or be developed on Mac OS X, let us consider the following examples:
We saw earlier that the Mac OS X kernel understands only the Mach-O binary executable format. Although Mach-O is the preferred runtime architecture, it is possible to run certain legacy format binaries on Mac OS X.
The Mac OS X kernel could be seen as an application environment for specialized applicationsdynamically loadable kernel extensionsthat execute in the kernel's address space. 2.11.1. BSDThe BSD application environment in Mac OS X is similar to, but not the same as, a traditional user-level environment on a BSD-based Unix system. It provides POSIX APIs, BSD-specific APIs, and some Unix-flavored APIs that export Mac OS Xspecific functionality. You can use the BSD environment for writing Unix tools, daemons, and shell scripts. In many cases, programs targeted for the Mac OS X BSD environment would be readily portable to other Unix systems and vice versa. The standard libraries and headers for the BSD environment reside in their traditional Unix locations: /usr/lib/ and /usr/include/, respectively.
Technically, many header files in /usr/include/ are part of the System framework. However, the System.framework directory neither contains nor links to these headers since the C compiler searches in /usr/include/ by default. 2.11.2. The X Window SystemThe X Window System could be seen as a graphical extension to the BSD environment. Mac OS X includes an optimized X Window server (/usr/X11R6/bin/Xquartz) along with a modern X Window environment. The X server is integrated with the Mac OS X Quartz subsystem. It conceptually sits atop the native Core Graphics APIs, tying into the native Mac OS X event system. Through this architecture, the X server enjoys hardware acceleration. The environment includes quartz-wman X Window manager with the native Mac OS X look-and-feel that allows X applications to run alongside native Mac OS X programs. quartz-wm provides Aqua window controls, drop shadows, integration with the Dock, and so on. Although the X server's default operating mode is rootless, it can also be run in full-screen mode.
Even though the Mac OS X user interface does not use focus-follows-mouse mode, it is possible to configure quartz-wm to enable this mode for X Window applications. With this mode, X application windows can be focused by simply moving the mouse pointer over them. To enable this mode, the wm_ffm Boolean property must be set to true in the com.apple.x11.plist file. Because of the availability of the BSD and X Window environments, it is usually straightforward to port existing Unix applications to Mac OS X simply by recompiling them, with little or no source modification. 2.11.3. CarbonThe Carbon application environment contains APIs based on the original Mac OS 9 APIs. In fact, some of Carbon's constituent interfaces date back to Mac OS 8.1. The Carbon interfaces are procedural in nature and are implemented in the C programming language. Carbon was originally designed to provide an easy development migration path from Mac OS 8 and Mac OS 9 to newer systems. It allows a compliant application, one that uses only features supported on both Mac OS 9 and Mac OS X, to run natively on both systems. It is implemented as a framework (Carbon.framework) on Mac OS X, whereas it is implemented as a system extension (CarbonLib) on Mac OS 9. 2.11.3.1. Support for CFM BinariesThe Code Fragment Manager (CFM) was a part of older Mac OS versions. It loaded fragments of PowerPC code from Preferred Executable Format (PEF) files into memory and prepared them for execution. A fragment is an arbitrarily sized basic unit of executable code and its associated data. It has certain well-defined properties and a method of addressing its contents. The following are examples of fragments:
Besides mapping fragments into memory, the CFM's responsibilities included releasing fragments when they were no longer needed, resolving references to symbols imported from other fragments, and providing support for special initialization and termination routines. The Mac OS X native runtime architecture (dyld/Mach-O) is not the same as that on Mac OS 9 (CFM/PEF). All Mac OS X libraries, including those that are part of Carbon, use the Mach-O format. However, Carbon supports the CFM on Mac OS X for Mac OS 9 compatibilityit is possible to create and run CFM applications on Mac OS X. In fact, an application that must run on both systems either must be compiled separately for the two systems or must be a CFM application. Carbon uses the LaunchCFMApp helper application[47] to run programs created for the CFM. LaunchCFMApp can run only native PowerPC code. It does not support resource-based fragments. Moreover, Carbon provides a one-way bridge to CFM applications to link to Mach-O code. Using this bridge, a CFM application can call a Mach-O library, but not vice versa.
2.11.3.2. Carbon APIsCarbon does not include all of the old APIs, but it contains a subset (about 70%) that covers most of the functionality used by typical applications. APIs that are not critical, or are no longer applicable due to radical differences between Mac OS X and earlier systems, have been dropped in Carbon. These include APIs that were specific to the 68K architecture, those that accessed the hardware directly, and those that were replaced by improved APIs. The following are noteworthy features of Carbon.
The following are examples of Carbon's subframeworks.
There are several frameworks that, although usable from other environments, are primarily for use by Carbon applications and are considered part of the Carbon environment. These include the Application Services, Core Foundation, and Core Services frameworks. Thus, Carbon provides procedural interfaces both for GUI development and for lower-level development involving manipulation of system resources, event handling, and data management. From a programmer's standpoint, it is generally easier to create an application from scratch using Cocoa (see Section 2.11.4) rather than Carbon, since Cocoa automatically provides several features that would require explicit coding in Carbon. For example, Cocoa objects by default provide many aspects of a well-behaved Mac OS X application: document management, window management, opening and saving of documents, pasteboard behavior, and so on. Similarly, the Core Data framework (see Section 2.11.4.2), which allows modeling and lifecycle management of data, is accessible only to Cocoa programs. 2.11.4. CocoaThe Cocoa environment provides object-oriented APIs for rapid application development in the Objective-C and Java programming languages.[50] Cocoa is both a collection of APIs and a set of visual tools that are particularly useful for rapid prototyping, data modeling, and overall reduction in design and development efforts. Examples of such tools include the Interface Builder and Xcode's class- and data-modeling tools. Interface Builder allows a programmer to create most (and often all) of an application's user interface graphically rather than programmatically. The class-modeling tool allows the programmer to visualize, browse, and annotate classes in terms of class relationships and the protocols they implement. The data-modeling tool allows the programmer to visually design a schema for application data in terms of entities that constitute the data and the relationships between them.
Apple recommends Cocoa as the preferred way to develop typical applications on Mac OS X. Between Cocoa and Carbon, you should use Cocoa unless your desired functionality is available only through Carbon, you must have legacy compatibility, or you must use C-based procedural interfaces. A Cocoa application can call Carbon APIs. It is possible, and common, for an application to be linked against both the Carbon and Cocoa frameworks. iDVD, iMovie, and Safari are examples of such applications. Cocoa is an important inheritance from NeXT, as indicated by the various names with the "NS" prefix in Cocoa APIs. Many of the Cocoa APIs are largely based on OpenStep frameworks. Cocoa primarily consists of two object-oriented frameworks: Foundation (Foundation.framework) and Application Kit (AppKit.framework). Several other frameworks add specific functionality to Cocoa, such as Core Data, PDF Kit, and QuickTime Kit. The Foundation framework provides fundamental classes and methods for bundle access, data management, file access, interprocess communication, memory management, network communication, process notification, and various low-level features. The Application Kit provides classes that implement user-interface elements such as windows, dialogs, controls, menus, and event handling. Core Data makes object lifecycle management easier by providing classes and methods for data management.
Cocoa is effectively an umbrella framework consisting of the Foundation, Application Kit, and Core Data subframeworks. The dynamic library inside Cocoa.framework is a wrapper that links to these frameworks. Consequently, linking with Cocoa.framework links in these (effective) subframeworks. However, in this particular case, the subframeworks are also available for individual linking. This is not the case with most umbrella frameworks, where it is illegal to attempt to link to a specific subframework. 2.11.4.1. Nib FilesWhen creating user interfaces with the Interface Builder, you will often come across nib files. As we saw earlier, the term stands for NeXT Interface Builder. A nib file contains descriptions of some or all of an application's user interface along with references to any resources (e.g., images and audio) that the interface may use. It is essentially an archive. Usually there is a "main" nib file that contains an application's main menu and other user-interface elements intended to appear when the application starts. During an application's execution, its nib files are opened and user-interface objects are unarchived. From the standpoint of the Model-View-Controller (MVC) design pattern, nib files define the view part of an application, while also defining connections into controller instances. The nibtool command-line program can be used to print, update, and verify the contents of a nib file. Figure 226 shows an example. Figure 226. Using nibtool to view the contents of a nib file
2.11.4.2. Core DataCore Data is a Cocoa framework that facilitates data-model-driven application development through fine-grained management of data objects. Core Data's primary benefits are for applications that have a highly structured data model to begin with.[51] In such cases, the data model can be represented by a schema, which in turn can be built using graphical tools in Xcode. Therefore, instead of defining data structures programmatically, developers can create visual descriptionsor modelsof data objects.[52] The application accesses the data through the Core Data framework, which is responsible for creating and managing instances of the data model.
Examples of applications that are good candidates for Core Data include Mail, iTunes, and Xcode. Each of these applications uses highly structured data: mailbox files, music libraries, and project files, respectively. Core Data offers several benefits to the developer, such as those listed here.
The file formats supported by Core Data vary in several properties: atomic access, human readability, performance, and scalability. For example, SQLite offers the best performance and is the most scalable. However, it is not human readable. XML is slower but is human readable. Since Core Data's essence is model-driven development, the most critical abstraction from the developer's standpoint in Core Data is the model, which is akin to an entity-relationship (ER) diagram. A model contains the following key elements.
Core Data applications typically use Core Data APIs to load models from storage into memory. The generic data object in Core Data is an instance of the NSManagedObject class. It is also a required superclass for any custom data object classes. As shown in Figure 227, the following primary components of the Core Data architecture interact in a logical "stack"[57] at runtime.
Figure 227. A Core Data stack
If Core Data is used judiciously, it can significantly reduce the amount of code that a developer would have to otherwise write. 2.11.5. WebObjectsWebObjects is an independent Apple productit is not a part of Mac OS X. It provides an application environment for developing and deploying Java server applications and Web Services. Using WebObjects frameworks and tools, developers can also create user interfaces for various types of web content, including database-driven and dynamically generated content. As we noted in Chapter 1, several Apple web sites are implemented using WebObjects. 2.11.6. JavaThe Java environment is a core component of Mac OS X. It includes the Java runtime and the Java Development Kit (JDK), which are accessible both through the command line and through Xcode. The Java runtime includes the HotSpot Java virtual machine (JVM) with just-in-time (JIT) bytecode compilation. It can also treat Java archivesor jar filesas shared libraries. The Java Virtual Machine framework (JavaVM.framework) contains Java classes in jar files, command-line programs such as java and javac,[58] headers, documentation, Java Native Interface (JNI) libraries, and support libraries.
Cocoa includes Java packages corresponding to the Foundation and the Application Kit frameworks. Therefore, Cocoa applications can be created using Java as the programming language instead of Objective-C. Moreover, Java programs can call Carbon and other frameworks via JNIa standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. In particular, Java applications can use Mac OS X native technologies such as QuickTime and Carbon. Since the Swing implementation on Mac OS X generates native Mac OS X user-interface elements, Swing-based Java applications have the same look-and-feel as Cocoa applications written using Objective-C.
The Cocoa-Java programming interface is deprecated in Mac OS X versions later than 10.4. Apple announced in mid-2005 that Cocoa features introduced in newer versions of Mac OS X will not be added to the Cocoa-Java API, requiring the Objective-C Cocoa API to employ the new features. Although Java is considered an application environment, the Java subsystem can itself be represented as different layers, as depicted in Figure 21. For example, the JVM along with the core JDK packages are analogous to the Core Services layer. In fact, the JVM conceptually provides the combined functionality of a computer system's hardware and the operating system kernel. 2.11.7. QuickTimeQuickTime's functionality is available to applications through various APIs such as those listed here.
2.11.8. ClassicClassic is a binary compatibility environment for running unmodified Mac OS 9 applications on the PowerPC version of Mac OS X. Classic functionality is provided through a combination of the following components.
Classic Startup is a Mach-O application that runs Mac OS 9 within its address space. It provides a hardware abstraction layer between Mac OS 9 and Mac OS X by virtualizing traps, system calls, and interrupts. It runs in a protected memory environment, with multiple Mac OS 9 processes within it layered on top of a single Mac OS X BSD process. Each Carbon application in Mac OS 9 has its own Carbon Process Manager process. In this sense, Classic support in Mac OS X is essentially "Mac OS 9 in a process." However, note that the Classic Startup application itself is multithreaded. In certain ways, Classic is "more" than Mac OS 9, since its integration with Mac OS X allows sharing of resources, as illustrated by the following examples.
Classic Startup is not an emulatorit is a virtualizer. Nevertheless, it allows both 68K-based Mac OS 9 applications and PowerPC-based CFM applications[59] to run under Mac OS X. There is emulation involved in running 68K code, but that emulation was part of Mac OS 9 and remains unchanged.
As we saw in Section 2.11.3.1, another legacy runtime environment is provided by the CFM, which uses PEF binaries.
2.11.9. RosettaThe x86 version of Mac OS X uses a binary translation process called Rosetta that allows PowerPC executablesboth CFM and Mach-Oto run on x86-based Macintosh computers. Like Classic, Rosetta is meant as a technology devised to help transition from one platform to another. It is limited in the type of executables it supports. Examples of PowerPC executables it does not support include the following:
For an application to run successfully under Rosetta, all components of the application, including loadable plug-ins, must be PowerPC-based. Rosetta is launched by the kernel to handle a file that is one of the supported PowerPC executable types. Rosetta code resides in the same Mach task as the "guest" executable. It dynamically translateswith optimizationsblocks of PowerPC code to x86 code, while alternating between code translation and code execution. To improve translation performance, Rosetta caches blocks of translated code. |