Seen through the lens of Model-View-Controller, the core application architecture of Cocoa concerns itself with the view layer of applications. It deals primarily with the raw mechanics of event handling and drawing, providing an efficient model for how an application presents itself to users and allows users to interact with it. But in a real application, these things don't exist in a vacuum. The other kinds of MVC objects in an application—the controller and model objects—give significance and content to the mechanics of drawing and event handling.
Note: The MVC design pattern is described in “The Model-View-Controller Design Pattern.”
Cocoa makes several other architectures available to software developers. These architectures are all mostly concerned with the controller and (especially) the model objects of an application. They are based on several design patterns in addition to Model-View-Controller, particularly object modeling (described in “Object Modeling”). Another thing they have in common is that they are intended to make the life of a Cocoa developer easier.
Document Architecture
Application Scriptability
Core Data
Many applications let users create and edit documents: unique aggregations of data presented in windows with identical user interfaces. Word processors, photo-image editors, and web browsers are examples of document-based applications. These applications have similar features. They enable users to create new documents, save those documents to files, and then open those documents later. Document-based applications also validate menu items, monitor each document's edited status, manage document windows, and respond appropriately to application-wide events (such as termination). Often they can have different internal representations of document data.
Cocoa offers developers an architecture that reduces the effort required to implement a document-based application with features such as these. The essential component of this architecture includes three Application Kit classes: NSDocument
, NSDocumentController
, and NSWindowController
. In a document-based Cocoa application, objects of these three classes have distinct spheres of responsibility and a cascading series of relationships with each other based on ownership and management (Figure B-1).
A Cocoa application that is based on the document architecture has a single NSDocumentController
object. This object owns and manages one or more NSDocument
objects. Each of these NSDocument
objects, in turn, creates and manages one or more NSWindowController
objects. And each NSWindowController
object is associated with a window of the document. (A document can have multiple windows.) An NSWindowController
object manages the presentation of the document.
Each of the three kinds of objects in the Cocoa document architecture has a specific responsibility which is dictated by its MVC role:
The NSDocumentController object manages the application's documents. It initiates and coordinates the creation of new documents, the saving of edited documents, and the opening of saved documents. It plays the MVC role of a coordinating controller for the entire application. The NSDocumentController
object is provided automatically for document-based applications. You generally do not need to subclass it.
NSDocumentController
gets the information it needs to manage documents from the document-type metadata specified in the application's information property list (Info.plist
). This metadata tells the application the extensions, HFS type code, MIME types, icon, and NSDocument
subclass (if applicable) of each document the application can read and write.
An NSDocument object manages the model objects of a document. In MVC terms, an NSDocument
object is a model-controller, a controller whose management responsibility is shifted towards the model layer. NSDocument
is an abstract class, and you must create a custom subclass of it that has knowledge of the document's data, as encapsulated in model objects. The instance of that subclass must be able to read data from a file and from it re-create the document's model objects, and it must be able to save the document's current collection of model objects to a file. Occasionally it may have to maintain more than one internal representation of document data. An NSDocument
object also owns and manages one or more NSWindowController
objects.
An NSWindowController object manages the presentation of the document in a window. In MVC terms, a NSWindowController
document is a view-controller: Its concern is managing the window in which document data is displayed. For simple applications you might not need to create a custom subclass of NSWindowController
; the default instance can handle rudimentary window-management chores while the NSDocument
object can incorporate knowledge of the view layer. But in most cases you should add the knowledge of the document's view objects to an NSWindowController
subclass. An instance of this subclass is typically the File's Owner of a document nib file. A multi-window document can have several different NSWindowController
objects, one for each window.
Xcode provides a project template for Cocoa applications based on the document architecture. When you create a project using this template, you get an NSDocument
subclass (named MyDocument
) with stub implementations of the required method overrides. You also get a document nib file with File's Owner set to MyDocument
.
Further Reading: For a complete description of the document architecture, see Document-Based Applications Overview.
AppleScript is a scripting language and an interprocess communications technology that many Macintosh power users are familiar with. When compiled and run, an AppleScript script controls an application by sending it commands and may receive data in return.
To be the target of AppleScript commands, an application must be made scriptable. A scriptable application offers its behavior and data in response to AppleScript-generated interprocess messages, called Apple events. Production-quality applications generally should be scriptable. You want to make what your application can do available to as many users as possible, including scripters and users of the Automator application.
Cocoa provides runtime support for scriptable applications. When an application's scriptability information is first needed, the Application Kit loads it and automatically registers Apple event handlers for the supported commands. When the application receives an Apple event for a registered command, the Application Kit instantiates a script command object, initializing it with information obtained from the application's scriptability information. This information enables it to find the scriptable objects in the application on which the command should operate. The Application Kit then executes the command and the scriptable objects perform the work requested. If those objects return a value, the Application Kit packages the value in an Apple event and returns it to the originating script.
For this runtime support to be effective, you must make the application scriptable. This task has several components:
You must supply the application's scriptability information.
The scriptability information specifies the terminology that scripts can use to target the application and its objects. It also includes information about how the application implements support for its terminology. You provide scriptability in one of two formats. The preferred format is an XML-based scripting definition—also called an sdef format because the extension of the file is .sdef
. The second, older format consists of a pair of property list files: a script suite file and a script terminology file.
Both formats contain the same scriptability information. They define the terminology to be used in scripts and describe the scriptable objects of the application by specifying the classes, commands, constants, and other information that AppleScript and Cocoa need to execute AppleScript commands.
You must implement any classes or methods needed to support scriptability.
Cocoa includes supports for common commands and other terms (such as get
, set
, window
, and document
) in the Standard suite. (In AppleScript, terms associated with related operations are collected in suites). It also provides the Text suite for scriptable operations on objects of the Cocoa text system. If your application has scriptable operations that can't be performed by the commands defined in the Standard or Text suites, it must define additional command classes. In addition, the application must implement an object-specifier method for each scriptable class; this method describes an object of the class and locates it within a containment hierarchy of the application's objects.
You must properly design your application's model and (possibly) its controller objects.
A Cocoa application that is scriptable should be designed according to the Model-View-Controller (MVC) design pattern, which separates the objects of the application into assigned roles. The model objects of the application are generally the objects that provide scriptability (although controller objects can sometimes be scriptable objects too). The scriptable classes of the application should be compliant with key-value coding (KVC). KVC is a mechanism that allows an object property to be fetched and set indirectly by a key. At runtime, command objects use KVC to find the scriptable objects on which to operate.
You implement KVC-compliance by incorporating the name of the property—which, by default, is also its key—in the instance variable that holds the property or the accessor methods of the class that get and set the property. As you design the classes for your scriptable (and generally model) objects, you also specify in the application's scriptability information the keys for these objects, the scriptable properties of these objects, and the element classes they contain.
For more on the design pattern on which KVC is based, see “Object Modeling.”
Separately from its support for scriptability, Cocoa automatically handles certain Apple events an application receives from other processes on a system. “Handling Apple Events” describes the Apple events and how Cocoa handles them.
Further Reading: Cocoa Scripting Guide explains Cocoa application scriptability in detail.
Core Data is a Cocoa framework that provides an infrastructure for managing object graphs, including support for persistent storage to a variety of file formats. Object-graph management includes features such as undo and redo, validation, and ensuring the integrity of object relationships. Object persistence means that Core Data saves model objects to a persistent store and fetches them when required. The persistent store of a Core Data application—that is, the ultimate form in which object data is archived—can range from XML files to SQL databases. Core Data is ideally suited for applications that act as front ends for relational databases, but any Cocoa application can take advantage of its capabilities.
The central concept of Core Data is the managed object. A managed object is simply a model object that is managed by Core Data, but it must be an instance of the NSManagedObject
class or a subclass of that class. You describe the managed objects of your Core Data application using a schema called a managed object model. (The Xcode application includes a data modeling tool to assist you in creating these schemas.) A managed object model contains descriptions of an application's managed objects (also referred to as entities). Each description specifies the attributes of an entity, its relationships with other entities, and metadata such as the names of the entity and the representing class.
In a running Core Data application, an object known as a managed object context is responsible for a graph of managed objects. All managed objects in the graph must be registered with a managed object context. The context allows an application to add objects to the graph and remove them from it. It also tracks changes made to those objects, and thus can provide undo and redo support. When you're ready to save changes made to managed objects, the managed object context ensures that those objects are in a valid state. When a Core Data application wishes to retrieve data from its external data store, it sends a fetch request—an object that specifies a set of criteria—to a managed object context. The context returns the objects from the store that match the request after automatically registering them.
A managed object context also functions as a gateway to an underlying collection of Core Data objects called the persistence stack. The persistence stack mediates between the objects in your application and external data stores. The stack consists of two different types of objects, persistent stores and persistent store coordinators. Persistent stores are at the bottom of the stack. They map between data in an external store—for example, an XML file—and corresponding objects in a managed object context. They don't interact directly with managed object contexts, however. Above a persistence store in the stack is a persistent store coordinator, which presents a facade to one or more managed object contexts so that multiple persistence stores below it appear as a single aggregate store. Figure B-2 shows the relationships between objects in the Core Data architecture.
Core Data includes the NSPersistentDocument
class, a subclass of NSDocument
that helps to integrate Core Data and the document architecture. A persistent-document object creates its own persistence stack and managed object context, mapping the document to an external data store. An NSPersistentDocument
object provides default implementations of the NSDocument
methods for reading and writing document data.
© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-11-19)