text:
Apple Cocoa Bindings Programming Topics Manuel Apple sur Fnac.com - Pour voir la liste complète des manuels APPLE, cliquez ici
TELECHARGER LE PDF sur :
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaBindings/CocoaBindings.pdfCommander un produit Apple sur Fnac.com
Voir également d'autres Guides et documentation APPLE :
Apple-Compressor-4-ユーザーズマニュアル Japon
Disque dur, ATA parallèle Instructions de remplacement
Manuale Utente PowerBookG4
Power Mac G5 Guide de l'utilisateur APPLE
Guide de l'utilisateur PAGE '08 APPLE
Guide de l'utilisateur KEYNOTE '09 APPLE
Guide de l'Utilisateur KEYNOTE '3 APPLE
Guide de l'Utilisateur UTILITAIRE RAID
Guide de l'Utilisateur Logic Studio
Power Mac G5 Guide de l'utilisateur APPLE
Guide de l'utilisateur PAGE '08 APPLE
Guide de l'utilisateur KEYNOTE '09 APPLE
Guide de l'Utilisateur KEYNOTE '3 APPLE
Guide de l'Utilisateur UTILITAIRE RAID
Guide de l'Utilisateur Logic Studio
Guide de l'utilisateur ipad Pour le logiciel iOS 5.1
PowerBook G4 Premiers Contacts APPLE
Guide de l'Utilisateur iphone pour le logiciel ios 5.1 APPLE
Guide de l'utilisateur ipad Pour le logiciel iOS 4,3
Guide de l'utilisateur iPod nano 5ème génération
Guide de l'utilisateur iPod Touch 2.2 APPLE
Guide de l'utilisateur QuickTime 7 Mac OS X 10.3.9 et ultérieur Windows XP et Windows 2000
Guide de l'utilisateur MacBook 13 pouces Mi 2010
Guide de l'utilisateur iPhone (Pour les logiciels iOS 4.2 et 4.3)
Guide de déploiement en entreprise iPhone OS
Cocoa Bindings
Programming TopicsContents
Introduction to Cocoa Bindings Programming Topics 7
Who Should Read This Document 7
Organization of This Document 7
See Also 8
What Are Cocoa Bindings? 10
The Advantages of Using Bindings 10
The Model-View-Controller Design Pattern 11
What Is a Binding? 12
A Simple Example 12
Binding Options 14
Extending the MVC Design Pattern 15
Supporting Technologies 16
Key-Value Binding 16
Key-Value Coding 17
Key-Value Observing 18
Why Are NSControllers Useful? 19
NSController Classes 19
What Can You Bind? 20
Real-World Example 20
How Do Bindings Work? 23
Overview of the Supporting Technologies 23
The Supporting Technologies in Detail 25
Establishing Bindings with Key-Value Binding 26
NSEditor/NSEditorRegistration 26
Key-Value Coding 26
Key-Value Observing 27
Unbinding 29
Bindings in More Detail 29
Responding to Changes 32
View-Initiated Updates 32
Model-Initiated Updates 34
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
2Providing Controller Content 37
Setting the Content of a Controller 37
Traversing Tree Content with an NSTreeController 39
Specifying the Class of a Controller's Content 40
Automatically Prepares Content 40
Programmatically Modifying a Controller's Contents 41
Modifying Controller Content by Target-Action 42
De-coupling a Controller from its Content Bindings 44
Working With a Controller's Selection 45
Getting a Controller's Currently Selected Objects 45
Changing the Current Selection 46
Changing the Selection by Object 46
Getting and Setting Selection by Index 47
Setting the Selection Behaviors 48
Avoids Empty Selection 48
Selecting Objects Upon Insertion 49
Always Uses Multiple Values Marker 49
Preserves Selection 50
Selects All When Setting Content 50
Bindings Message Flow 52
Changing the Value of a Model Property 53
User Updates a Value in the User Interface 56
User Defaults and Bindings 61
What Is NSUserDefaultsController? 61
The Shared User Defaults Controller 61
Binding to the Shared User Defaults Controller 62
initialValues Versus NSUserDefaults registerDefaults: 62
Search Order for Defaults Values 64
Programmatically Accessing NSUserDefaultsController Values 64
Creating a Master-Detail Interface 65
What's a Master-Detail Interface? 65
Creating Models 66
Creating Views 67
Creating Controllers 68
Binding Controllers to Models 69
Binding Views to Controllers 70
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
3Binding the Master Interface 70
Binding the Detail Interface 71
Displaying Images Using Bindings 73
Creating Models 73
Creating Views 74
Creating Controllers 74
Binding Views to Controllers 74
Using a Value Transformer to Convert Paths 75
Creating Custom Value Transformers 75
Registering Value Transformers 76
Binding Views to Controllers Using Transformers 76
Implementing To-One Relationships Using Pop-Up Menus 78
Creating Models and Controllers 78
Creating Views 79
Binding Views to Controllers 79
Filtering Using a Custom Array Controller 81
Overriding arrangeObjects: 81
Updating the Search String 82
Controller Key-Value Observing Compliance 83
NSUserDefaultsController 83
NSObjectController 83
NSArrayController 84
NSTreeController 84
Troubleshooting Cocoa Bindings 86
My collection controller isn't displaying the current data 86
Changing the value in the user interface programmatically is not reflected in the model 86
Changing the value of a model property programmatically is not reflected in the user interface 87
Binding to the incorrect key path 87
The bindings of my custom view are disabled in Interface Builder 88
An uneditable/visible/disabled NSTextField becomes editable/hidden/enabled 89
Binding a control to a value that is an unsigned int causes an exception 89
The view bound to an NSTreeController is not displaying data 89
A table column containing NSPopUpButtonCell items is not sortable 89
Document Revision History 90
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
4Figures and Listings
What Are Cocoa Bindings? 10
Figure 1 Controllers provide glue code 11
Figure 2 A simple Cocoa application 12
Figure 3 Slider example using target-action 13
Figure 4 Slider demonstration using bindings 13
Figure 5 Displaying temperature using transformers 14
Figure 6 Typical bindings configuration using existing controller 15
Figure 7 Bindings established using key-value binding 16
Figure 8 Using key-value-coding to update values 17
Figure 9 Key-value observing—registering observers 18
Figure 10 Key-value observing—notification of observers 18
Figure 11 User interface for Combatants application 20
Figure 12 Combatant class 21
Figure 13 Combatants application managed by bindings 21
How Do Bindings Work? 23
Figure 1 Example drawing application 24
Figure 2 Bindings for example graphics application 24
Figure 3 The complete edit cycle 25
Figure 4 Key-value coding in Cocoa bindings 27
Figure 5 Key-value observing in Cocoa bindings 28
Figure 6 Bindings for a joystick's angle in Interface Builder 29
Listing 1 Interface for the Joystick class 30
Listing 2 Partial implementation of the bind:toObject:withKeyPath:options method for the Joystick class
Listing 3 Update method for the Joystick class 33
Listing 4 Observing method for the Joystick class 35
Providing Controller Content 37
Figure 1 Master-detail interface with and without contentArrayForMultipleSelection 38
Working With a Controller's Selection 45
Figure 1 Preserves selection example 50
Figure 2 Selects all when setting content example 51
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
5Bindings Message Flow 52
Figure 1 Message flow when modifying the value of a model object property 53
Figure 2 Message flow in response to the user changing a value in an NSTextField 57
Figure 3 Message flow in response to the user changing a value in an NSTextField, view-controller
validation 58
User Defaults and Bindings 61
Listing 1 Binding the userName defaults key to an NSTextField programmatically 62
Listing 2 Changing the initial values of the sharedUserDefaultsController instance 63
Creating a Master-Detail Interface 65
Figure 1 A master-detail interface 66
Figure 2 An object model 67
Figure 3 An array controller Attributes pane 68
Figure 4 An array controller Bindings pane 69
Figure 5 NSTableColumn Bindings pane 71
Displaying Images Using Bindings 73
Figure 1 Using an NSImageCell in an NSTableColumn 73
Figure 2 Bindings pane of an NSTableColumn 77
Listing 1 PathTransformer implementation file 75
Implementing To-One Relationships Using Pop-Up Menus 78
Figure 1 Using pop-up menus to represent to-one relationships 78
Filtering Using a Custom Array Controller 81
Listing 1 Filtering implementation of arrangeObjects: 81
Listing 2 Updating searchString 82
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
6Cocoa bindings is a collection of technologies you can use in your applications to fully implement a
Model-View-Controller paradigm where models encapsulate application data, views display and edit that data,
and controllers mediate between the two. Cocoa bindings reduces the code dependencies between models,
views and controllers, supports multiple ways of viewing your data, and automatically synchronizes views
when models change. Cocoa bindings provides extensible controllers, protocolsfor models and viewsto adopt,
and additions to classes in Foundation and the Application Kit. You can eliminate most of your glue code by
using bindings available in Interface Builder to connect controllers with models and views.
Who Should Read This Document
Cocoa bindings is ideal for developers writing new applications who have some familiarity with Cocoa, and
for developers of existing applications who want to simply clean up or eliminate their existing glue code. In
most cases, Cocoa bindings can be used to replace traditional Cocoa mechanisms such as target-action,
delegation, and some data source protocols. However, great care has been taken to ensure that both approaches
can be used side by side within the same application.
This document assumes that you have read Key-Value Coding Programming Guide , Key-Value Observing
Programming Guide and Value Transformer Programming Guide .
Important: Cocoa bindings is available to Cocoa Objective-C applications running OS X version 10.3 and
Organization of This Document
The following articles cover key concepts in understanding how Cocoa bindings works:
"What Are Cocoa Bindings?" (page 10) describes the advantages that Cocoa bindings offers developers;
provides a brief summary of how they work; and what design patterns you should use to adopt the
"How Do Bindings Work?" (page 23) describes in detail the technologies supporting Cocoa bindings and
how they interact.
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
Introduction to Cocoa Bindings Programming
"User Defaults and Bindings" (page 61) describes the role of the NSUserDefaultsController and how it
works with NSUserDefaults.
"Providing Controller Content" (page 37) describes how to set and modify the content of NSObjectController
and its subclasses.
"Working With a Controller's Selection" (page 45) describes how to get a controller's selection and change
the current selection.
"Bindings Message Flow" (page 52) illustrates the flow of messages between model, view and controller
objects in a bindings application.
These articles contain tasks that teach you how to use Cocoa bindings:
"Creating a Master-Detail Interface" (page 65) explains how to implement a basic master-detail interface
where a table view is used in the master interface to display a collection of objects, and other views used
in the detail interface to display the selected object in the collection.
"Displaying Images Using Bindings" (page 73) describes the various options when displaying images in
columns and contains an example of a custom value transformer.
"Implementing To-One Relationships Using Pop-Up Menus" (page 78) explains how to implement editable
to-one relationship as pop-up menus.
"Filtering Using a Custom Array Controller" (page 81) explains how to add a search field to the master
interface to filter the objects it displays.
"Controller Key-Value Observing Compliance" (page 83) details the properties for which the controller
classes provide key-value observing change notifications.
"Troubleshooting Cocoa Bindings" (page 86) describes a number of common problems encountered with
Cocoa bindings applications and provides methods for correcting the issues.
See Also
There are other technologies, not fully covered in this topic, that are fundamental to how bindings work. You
may want to read these topics if you want a better understanding of the underpinnings of Cocoa bindings, or
if you want to use these technologies independent from bindings. For example, this topic does not explain
how to use the methods defined in the key-value observing protocol. Refer to these documents for more
● Developing Cocoa Applications Using Bindings: A Tutorial takes you through the steps of building the
familiar Currency Converter application using Cocoa bindings.
Introduction to Cocoa Bindings Programming Topics
See Also
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
8● Cocoa Bindings Reference enumerates the classes that support Cocoa bindings and provides descriptions
of the bindings for each class, along with the supported options and placeholders.
● Key-Value Coding Programming Guide covers all the features of the key-value coding protocol that allows
objects to indirectly access the properties of other objects.
● Key-Value Observing Programming Guide covers all the features of the key-value observing protocol that
allows objects to observe changes in other objects.
● Value Transformer Programming Guide describes how to use value transformers to convert values from
one type to another.
● Sort Descriptor Programming Topics describes how to use sort descriptors that specify how collections are
Introduction to Cocoa Bindings Programming Topics
See Also
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
9In the simplest functional sense, the Cocoa bindings technology provides a means of keeping model and view
values synchronized without you having to write a lot of "glue code." It allows you to establish a mediated
connection between a view and a piece of data, "binding" them such that a change in one is reflected in the
This article describes what the technology offers and how it makes writing applications easier. It also introduces
the idea that rather than completely reimplementing an existing application to make use of bindings, you can
incorporate bindings in stages.
This article also describes on a conceptual level how Cocoa bindings work, and the design patterns you should
adopt. It gives a brief overview of the Model-View-Controller design pattern, and why it is beneficial. It then
gives a conceptual overview of how the main technologies that underpin Cocoa bindings—key-value coding,
key-value observing, and key-value binding—work, and how they inter-relate. The article finally explains the
role of the controller classes that Cocoa bindings provide and why you should use them.
"How Do Bindings Work?" (page 23) describes the supporting technologies in greater detail.
The Advantages of Using Bindings
The Cocoa bindings technology offers a way to increase the functionality and consistency of your application
while at the same time decreasing the amount of code you have to write and maintain. It takes care of most
aspects of user interface management for you by allowing you to off load the work of custom glue code onto
reusable pre-built controllers. It helps you build polished, easy-to-use applications that leverage object
relationships, provide sortable tables, and include intelligent selection management.
Typically you do not need to completely rewrite your application in order to adopt Cocoa bindings. For example,
it is likely that you can factor out User Preferences to be managed by Cocoa bindings without affecting the
rest of an application. You will find it easier to make use of Cocoa bindings if your application adopts the
recommended design patterns.
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
What Are Cocoa Bindings?The Model-View-Controller Design Pattern
Cocoa applications generally adopt the Model-View-Controller (MVC) design pattern. When you develop a
Cocoa application, you typically use model, view, and controller objects, each of which performs a different
function. Model objects represent data and are typically saved to a file or some other permanent data store.
View objects display model attributes. Controller objects act as go-betweens, to make sure that what a view
displays is consistent with the corresponding model value and that any updates a user makes to a value in a
view are propagated to the model. An understanding of the MVC design pattern is essential to fully understand
and leverage Cocoa bindings. If you need to know more, read "The Model-View-Controller Design Pattern."
If you adopt the MVC design pattern, much of your application code is easier to reuse and extend—you can
reuse model and view classes in different applications. Much of the implementation of a controller object
consists of what is commonly referred to as "glue code." Glue code is the code that keeps the model values
and views synchronized, and is unique to each application. It is typically tedious and cumbersome to write,
contributes little to the fundamental function of the application, but you must do it well to provide a good
user experience.
Figure 1 Controllers provide glue code
firstName = "Jo"
lastName = "Jackson"
Document Window
First Jo
Last Jackson
Cocoa bindings replace much of the glue code with reusable controllers and provide an infrastructure that
allows you to connect the user interface with an application's data.
Cocoa uses a number of terms that are commonly used in computer science. To avoid misunderstanding, they
are defined in the "Terminology"section of Key-Value Coding ProgrammingGuide with their particularmeaning
in the context of Cocoa bindings.
What Are Cocoa Bindings?
The Model-View-Controller Design Pattern
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
11What Is a Binding?
A binding is an attribute of one object that may be bound to a property in anothersuch that a change in either
one isreflected in the other. For example, the "value" binding of a text field might be bound to the temperature
attribute of a particular model object. More typically, one binding might specify that a controller object
"presents" a model object and another binding might specify that the value of a text field be tied to the
temperature property of the object presented by the controller.
Although the following examples concentrate on simple cases, bindings are not restricted to the display of
textual or numeric values. Among other things, a binding might specify the color in which text should be
displayed, whether a view is hidden or not, or what message and arguments should be sent when a button is
A Simple Example
Take as an example a very simple application in which the valuesin a text field and a slider are keptsynchronized.
Consider first an implementation that does not use bindings. The text field and slider are connected directly
to each other using target-action, where each is the other's target and the action is takeFloatValueFrom:
as shown in Figure 2. (If you do not understand this, you should read Getting Started With Cocoa.)
Figure 2 A simple Cocoa application
Number 6.2
This example illustrates the dynamism of the Cocoa environment—the values of two user interface objects
are kept synchronized without writing any code, even without compiling. It also serves to illustrate the
target-action design pattern (for more details, read "The Target-Action Paradigm").
What Are Cocoa Bindings?
What Is a Binding?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
12The major flaw from which this example suffers is that, as it is, it has almost no real-world application. In order
to find out the value to which either the slider or the text field has been set, and update a model attribute
accordingly, you need connections to the text field and slider, and have to write some code. You typically use
a controller that is connected to both (using outlets) and to which both are connected (using target-action),
as illustrated in Figure 3 (page 13).
Figure 3 Slider example using target-action
Number 6.2
slider = slider
textfield = textfield
number = number
number = "6.2"
Instance variable setFloatValue:
When a user moves the slider, it sends an action message to its target (the controller). The controller in turn
updates the value in the model, and synchronizes the user interface (the text field and the slider). Although
this example is not particularly difficult, the situation becomes more complex if you use more complicated
models and displays, especially if you use, for example, table views that allow multiple selections, or if a value
may be displayed in a different window. And you have to write all the code to support this functionality.
Cocoa bindings uses prebuilt controller objects (subclasses of NSController) and supporting technologies to
keep values synchronized automatically. The application design for an implementation of the slider example
that uses bindings is shown in Figure 4.
Figure 4 Slider demonstration using bindings
Bind content
to object
Number 6.2
number = "6.2"
content = object
Bind value to
object's number
What Are Cocoa Bindings?
What Is a Binding?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
13Note that this implementation does not use the target-action pattern. The slider does not send an action
message to the controller. Instead, as the slider moves, it informs the controller directly that the value of its
content's number has changed and what the value is. The controller updates the model and in turn informs
the text field and slider that the value they are displaying has changed. (In examples assimple asthis controllers
are not really necessary, however in most cases they are.) The mechanisms used to relay information are
explained later in this article and in greater detail in "How Do Bindings Work?" (page 23), but it is important
to appreciate that in most cases you will not have to write any glue code.
Binding Options
Many bindings allow you to specify options to customize their behavior. There are three types of option: value
transformers, placeholders, and other parameters.
A value transformer, as its name implies, applies a transformation to a value. A value transformer may also
allow reverse transformations. The Foundation framework provides the abstract NSValueTransformer class and
several convenient transformers, including one that negates a value—that is, it turns a Boolean YES into NO
(and vice versa). You can also implement your own transformers.
To see how transformers might be useful, suppose that in the previous example the number in the model
represents temperature in degrees Fahrenheit, but that you want to display the value in Celsius. You could
implement a reversible value transformer that converts values from one scale to the other. If you then specify
it as the transformer option for the text field and slider, as shown in Figure 5 (page 14), the user interface
displays the temperature in Celsius, and any new values entered using the slider or text field converted to
Figure 5 Displaying temperature using transformers
Bind content
to object
temperature = 77.0
content = object
Celsius 25.0
Bind value to
object's temperature
using Fahrenheit to
Celsius transformer
To learn more about transformers read Value Transformer Programming Guide (the article also shows an
implementation of the Fahrenheit to Celsius transformer).
What Are Cocoa Bindings?
What Is a Binding?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
14Placeholder options allow you to specify what a view should display: if the value of the property to which it is
bound is null (nil); if there is no selection; if there is a multiple selection; or if for some other reason the value
is not applicable.
In addition to value transformers and placeholders, some bindings offer a variety of other options, such as
whether the value of the binding is updated as edits are made to the user interface item, or whether the
editable state of a user interface item is automatically configured based on the controller's selection. For a
complete list of all the binding options available, see Cocoa Bindings Reference .
Extending the MVC Design Pattern
The Cocoa bindings architecture extends the traditional Cocoa MVC configuration, where there is a single
custom-built controller that manages the user interface. It provides a set of reusable controller classes that
inherit from an abstract superclass, NSController. In a bindings-based application there may be several
controllers—your own (such as an NSWindowController subclass, managing a document's user interface) and
others that are subclasses of NSController and manage different parts of the user interface. You might also
create your own subclasses of the standard Application Kit controller classes—in particular you might subclass
NSArrayController to customize sorting and filtering behavior.
Other figures in this document present a convenient shorthand. Although the NSController instance is
conceptually bound directly to its model object, in most situations the binding will be "indirect," to a variable
in your document object, as shown in Figure 6.
Figure 6 Typical bindings configuration using existing controller
Celsius 25.0
Instance variable
temperature = "6.2"
object = myObject
content = object
Bind value to
Bind content to
What Are Cocoa Bindings?
What Is a Binding?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
15Supporting Technologies
Cocoa bindings rely primarily on two other technologies, key-value coding (KVC) and key-value observing
(KVO). Bindings themselves are established using key-value binding (KVB) as illustrated in Figure 7. In practice
you typically need to understand these technologies only if you want to create your own custom view with
bindings. If you want to use bindings, the only requirement that is imposed on you is that your model classes
must be compliant with key-value coding conventions for any properties to which you want to bind.
Key-Value Binding
A binding is established with a bind:toObject:withKeyPath:options: message which tells the receiver
to keep its specified attribute synchronized—modulo the options—with the value of the property identified
by the key path of the specified object. The receiver must watch for relevant changes in the object to which
it is bound and react to those changes. The receiver must also inform the object of changes to the bound
attribute. After a binding is established there are therefore two aspects to keeping the model and views
synchronized: responding to user interaction with views, and responding to changes in model values.
Figure 7 Bindings established using key-value binding
binding using
temperature = 77.0
content = object
NSObjectController WWiinnddooww
Celsius 25.0
binding using
In a view-initiated update a value changed in the user interface is passed to the controller, which in turn pushes
the new value onto the model. To preserve the abstraction required to allow this to work with any controller
or model object, the system uses a common access protocol—key-value coding.
In a model-initiated update models notify controllers, and controllers notify views, of changes to values in
which interest has been registered using a common protocol—key-value observing. Note that a model-initiated
update can be triggered by direct manipulation of the model—for example by a Scripted Apple event—or as
the result of a view-initiated update—a change to the temperature made by editing the Celsius field must be
propagated back to the slider.
What Are Cocoa Bindings?
Supporting Technologies
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
16Key-Value Coding
Key-value coding is a mechanism whereby you can access a property in an object using the property's name
as a string—the "key." You can also use key paths to follow relationships between objects. For example, given
an Employee class with an attribute firstName, you could retrieve an employee's first name using key-value
coding with the key firstName. If Employee has a relationship called "manager" to another Employee, you
could retrieve an employee's manager's first name using key-value coding with the key path
manager.firstName. For more details, see Key-Value Coding Programming Guide .
Recall that a binding specifies the key path to a property to which a given attribute is bound. If the value in
the slider or the text field is changed, it uses key-value coding—using the key path specified by the binding
as the key—to communicate that change directly to the controller, as illustrated in Figure 8. Note that the
arrows in this figure represent the direction in which messages are sent and in which information flows. The
new value is passed from the user interface widget to the controller, and from the controller to the model.
Figure 8 Using key-value-coding to update values
temperature = 77.0
content = object
NSObjectController WWiinnddooww
Celsius 25.0
using Key-Value
values using
What Are Cocoa Bindings?
Supporting Technologies
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
17Key-Value Observing
Key-value observing is a mechanism whereby an object can register with another to be notified of changes to
the value of a property. When one object is bound to another object, it registers itself as an observer of the
relevant property of that object. In the current example, the text field and slider register as observers of the
temperature property of the controller's content, as illustrated in Figure 9.
Figure 9 Key-value observing—registering observers
temperature = 77.0
content = object
NSObjectController WWiinnddooww
Celsius 25.0
Register as an
observer of the
Register as an
observer of the
Note that the arrows shown in Figure 9 indicate direction of observation, not of data flow. Observation is a
"passive" process (akin to registering to receive notifications from an NSNotificationCenter). When a value
changes, the observed object sends a message to interested observers to notify them, as illustrated in Figure
10. The arrows in Figure 10 show the direction in which messages are sent.
Figure 10 Key-value observing—notification of observers
temperature = 77.0
content = object
Celsius 25.0
Notify that
has changed
Notify that
has changed
What Are Cocoa Bindings?
Supporting Technologies
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
18Why Are NSControllers Useful?
Bindings can, in principle, be made between almost any two objects, provided that they are KVC-compliant
and KVO-compliant. A view could bind directly to a model object. Bindings-based applications, however, use
controller objects to manage individual model objects and collections of model objects and to interface to the
user preferences system.
It is possible to make bindings directly to your model objects or to controllers that do not inherit from
NSController—however you lose (or must reimplement) functionality provided by the Application Kit's controller
● NSController instances manage their currentselection and placeholder values. This allows a view to display
an appropriate value if the controller's selection is null, or if there is a multiple selection.
● NSController (and Application Kit user interface elements that support binding) implements the NSEditor
and NSEditorRegistration protocols. The NSEditorRegistration protocol provides a means for an editor (a
view) to inform a controller when it has uncommitted changes. The NSEditor protocol provides a means
for requesting that the receiver commit or discard any pending edits.
For example, if a user istyping in a text field and then clicks a button, the controller ensuresthat the model
object is updated with the complete contents of the text field before the button action takes place.
Although the methods are typically invoked on user interface elements by a controller they can also be
sent to a controller, for example in response to a user's attempt to save a document or quit an application.
NSController Classes
NSController is an abstract class. Its concrete subclasses are NSObjectController, NSUserDefaultsController,
NSArrayController, and NSTreeController. NSObjectController manages a single object and provides the
functionality discussed so far. NSUserDefaultsController provides a convenient interface to the preferences
NSArrayController and NSTreeController manage collections of model objects and track the current selection.
The collection controllers also allow you to add objects to, and remove objects from, the content collection.
The objects that the collection controllers manage don't even have to be in an array—your container can
implement suitable methods ("indexed accessor" methods, defined in the NSKeyValueCoding protocol) to
present the values to the controller as if they were in an array.
What Are Cocoa Bindings?
Why Are NSControllers Useful?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
19What Can You Bind?
You can make bindings for most of the Application Kit view classes, such as NSButton and NSTableView. Using
an array controller, for example, you can bind the contents of a pop-up menu to objects in an array. The
remainder of this article presents an example that is moderately complex. Although the details are intentionally
left vague it nevertheless serves to illustrate a number of points, and provides examples of more complex
Real-World Example
Consider a game application in which the user manages a number of combatants, from which they can select
one as an attacker. A combatant can carry three weapons, one of which isselected at any time. In the application,
the list of combatants is shown in a table view, the window's title shows the attacker's name, and a pop-up
menu shows the currently selected weapon, as shown in Figure 11 (page 20).
Figure 11 User interface for Combatants application
Selected Weapon
What Are Cocoa Bindings?
What Can You Bind?
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
20Combatants are represented by instances of the Combatant class. In the Combatant class, each weapon is
referenced as a separate instance variable, as shown in Figure 12. By implementing suitable "indexed" accessor
methods(defined by the key-value coding protocol), however, the Combatant class can allow an array controller
to access the weapons as if they were in an array.
Figure 12 Combatant class
weapon1 = dagger
weapon2 = sword
weapon3 = pike
selectedWeapon = weapon2
name = "Vlad"
When the user chooses an attacker from the table view, the window title is updated to reflect the attacker's
name, and the title of the pop-up menu is updated to reflect the attacker's selected weapon. When the user
activates the pop-up its contents are created dynamically from the set of weapons carried by the combatant.
When the user selects a menu item, the combatant's selected weapon is set to that corresponding to that
menu item. If a different attacker is selected, the pop-up, selection and window title update accordingly.
Figure 13 (page 21) illustrates how the user interface of the Combatants application can be implemented
using bindings. The table view is bound to an array controller that manages an array of combatants. The
window title is bound to the name of the selected combatant. The pop-up menu retrieves its list of items from
an array controller bound to the attacker's weapons"array," and itsselection is bound to the attacker'sselected
Figure 13 Combatants application managed by bindings
contentArray = combatants
contentArray =
Selected Weapon
weapon1 = dagger
weapon2 = sword
weapon3 = pike
selectedWeapon = weapon2
name = "Vlad"
Bind title to
Bind value to
contentArray to
content to
Bind selectedObject to
What Are Cocoa Bindings?
Real-World Example
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
21This example illustrates a number of points:
In an application you can use more than one controller object.
● Different aspects of a user interface element may be bound to different controllers.
● You can use your own custom model classes.
Finally, it should be emphasized that the example requires no actual code to set up the user interface—the
controllers and bindings can all be created in Interface Builder. This represents a considerable reduction in
programming effort compared with the traditional target-action based approach.
What Are Cocoa Bindings?
Real-World Example
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
22This article provides a conceptual explanation of how Cocoa bindings work. It describes:
● How connections between model and controller, and controller and view, are established using key-value
● Unbinding
● The NSEditor and NSEditorRegistration protocols
● The technologies that Cocoa bindings use to support communication between the model, view, and
controller, namely key-value coding, and key-value observing
● How the various technologies interact
You should already be familiar with the concepts presented in "What Are Cocoa Bindings?" (page 10).
Overview of the Supporting Technologies
This section presents an overview of the technologies that make Cocoa bindings work and how they interact.
They are discussed in greater detail in the following sections.
Cocoa bindings rely on other technologies—key-value coding (KVC) and key-value observing (KVO)—to
communicate changes between objects, and on key-value binding (KVB) to bind a value in one object to a
property in another. Cocoa bindings also use two protocols—NSEditor and NSEditorRegistration—that help
to ensure that any pending edits are either discarded or committed before user interface elements are disposed
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
How Do Bindings Work?To understand how these technologies work together, consider a drawing application that allows the user to
draw graphic objects such as circles and rectangles on screen. Among other properties, a graphic object has
a shadow that may be offset a variable distance from the center of the graphic at an arbitrary angle. An inspector
displays the offset and angle of the selected graphic object's shadow in a pair of text fields and a custom
view—a joystick—as shown in Figure 1.
Figure 1 Example drawing application
Offset: 15.0
Angle: 28.00
The implementation of the inspector is illustrated in Figure 2. Both the text fields and the joystick are bound
to the selection of an NSArrayController. The controller's contentArray is bound to an array of Graphic
objects. A Graphic hasinstance variablesto represent itsshadow's angle in radians and its offset from its center.
Figure 2 Bindings for example graphics application
shadowOffset = 15.00
shadowAngle = 0.86
selection = graphic
Offset: 15.0
Angle: 28.00
value bound to
value bound to
using radians to degrees
value transformer
offset bound to
angle bound to
using radians to degrees
value transformer
How Do Bindings Work?
Overview of the Supporting Technologies
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
24The text fields' values are bound to the angle and offset of the graphic object's shadow; the joystick provides
a graphical representation of angle and offset. The angle in the text field is displayed in degrees, and the angle
used internally by the joystick is specified in radians. The bindings for both of these specify a reversible value
transformer that converts between radians and degrees.
The complete sequence of events that occurs when a user edits a value in the angle text field is illustrated in
Figure 3 (page 25).
Figure 3 The complete edit cycle
shadowOffset = 15.00
shadowAngle = 0.86
selection = graphic
Offset: 15.0
Angle: 28.00
KVC + degrees
to radians
KVO + degrees
to radians
1. The user enters a new value in the Angle text field. The text field uses the NSEditorRegistration protocol
to indicate that an edit has begun, and when it is complete. The text field's binding specifies a reversible
radians-to-degrees value transformer, so the new value is converted to radians.
2. Using KVC, through the controller the view updates the model object's shadowAngle variable.
3. Through KVO, the model informsthe controller that an update has been made to its shadowAngle variable.
4. Through KVO, the controller informs the joystick and the angle text field that an update has been made
to its content's shadowAngle variable.
Notice that the Offset text field was not involved in the cycle in any way. Cocoa bindings impose no more
overhead than is necessary.
The next sections explain in greater detail how bindings are established and how the underlying technologies
The Supporting Technologies in Detail
This section first describes the technologies that support bindings and shows how they play their parts. It also
explains what steps you must take in order to take advantage of these technologies.
How Do Bindings Work?
The Supporting Technologies in Detail
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
25Establishing Bindings with Key-Value Binding
Key-value binding is used to establish bindings. The NSKeyValueBindingCreation informal protocol declares
methods to establish and remove bindings between objects. In addition, it provides a means for a class to
advertise the bindings that it exposes.
In most cases you need to use bind:toObject:withKeyPath:options:, and then only when you establish
bindings programatically. Use of the unbind: is discussed in "Unbinding." The other methods—the class
method exposeBinding: and the instancemethods exposedBindings and valueClassForBinding:—are
useful only in an Interface Builder palette.
Together the NSEditorRegistration and NSEditor protocols allow views to notify a controller that an edit is
underway and to ensure that any pending edits are committed as and when necessary.
The NSEditorRegistration informal protocol isimplemented by controllersto provide an interface for a view—the
editor—to inform the controller when it has uncommitted changes. When an edit is initiated, the view sends
the controller an objectDidBeginEditing: message. When the edit is complete (for example when the
user presses Return) the view sends an objectDidEndEditing: message.
The controller is responsible for tracking which editors have uncommitted changes and requesting that they
commit or discard any pending edits when appropriate—for example, if the user closes the window or quits
the application. The request takes the form of a commitEditing or discardEditing message, defined by
the NSEditor informal protocol. NSController provides an implementation of this protocol, as do the Application
Kit user interface elements that support binding.
Key-Value Coding
Key-value coding (KVC) provides a unified way to access an object's properties by name (key) without requiring
use of custom accessor methods. The NSKeyValueCoding protocol specifies among others two methods,
valueForKey: and setValue:forKey:, that give access to an object's property with a specified name. In
addition, the methods setValue:forKeyPath: and valueForKeyPath: give access to properties across
relationships using key paths of the form relationship.property , for example, content.lastName.
How Do Bindings Work?
The Supporting Technologies in Detail
2009-03-08 | © 2003, 2009 Apple Inc. All Rights Reserved.
26A binding for a given property specifies an object and a key path to a property of that object. Given this
information, the bound object can use key-value coding—specifically setValue:forKeyPath:—to update
the object to which it is bound without having to hard-code an accessor method, as illustrated in Figure 4.
Figure 4 Key-value coding in Cocoa bindings
shadowOffset = 15.00
shadowAngle = 0.86
selection = graphic
NSArrayController Shadow
Offset: 15.0
Angle: 28.00
Update to value in
controller passed
to model using KVC
Update to value
in view passed to
controller using KVC
Since Cocoa bindings rely on KVC, your model and controller objects must be KVC-compliant for other objects
to be able to bind to them. To support KVC you simply have to follow a set of conventions for naming your
accessor methods, briefly summarized here:
● For an attribute or to-one relationship named
cout is used:
Thereafter, you need only use a namespace prefix ("h" in the above example) with an element (separated
by a colon) to identify the element unambiguously. All child elements of the element with the namespace
declaration are associated with the same namespace through the prefix. The prefix-element name
combination (h:table from the example above) is called a qualified name. A namespace declaration
with no prefix after xmlns defines a default namespace, unlessthe value is an empty string, which means
"no namespace." The URI in a namespace declaration doesn't have to point to anything; it is just a
convenient way to get a unique name.
namespace prefix
A prefix defined in a namespace declaration to identify the namespace a particular element is associated
with. The namespace's qualified name (xmlns:localname ) appears only during output. All other operations,
such as those that get or set a namespace node's value, use the local name only. See also namespace.
To coalesce all adjacent child text nodes into a single text node while removing empty text nodes.
Normalization is highly recommended before performing XPath and XQuery queries.
Identifies by name the format either of an unparsed entity or an element bearing a specific notation
attribute; it can also identify the target of a processing instruction. A notation declaration gives a name
to the notation and an external identifier that enables a parser or its client to locate a helper application
that can process the data specified by the notation. Notations occur in attribute values, attribute-list
declarations, and entity declarations.
processing instruction
A construct that provides information to the application processing the XML document. The instructions
could instruct the application how, for example, to interpret the XML or display the results. Processing
instructions can occur within elements or at the top level of a document. The first word of the processing
instruction is called the target (its name) and every thing else is its object value. Example:
XML Glossary
2010-03-24 | © 2004, 2010 Apple Inc. All Rights Reserved.
qualified name
An element's full name, consisting of prefix, colon, and local name. See also namespace.
A collection of items, each of which can be a node or an atomic value. XQuery queries return a sequence
(an NSArray in Cocoa), which may contain only a single item.
A procedure that checks an XML document against the logical structure described by declarations in the
associated DTD (or other schema) to see if the XML conforms to it. Some of the constraints involved in
validation are proper element sequence and nesting, specification of required attributes, and correct
attribute type. For example, if an element is supposed to have one or more child elements but doesn't,
the document containing the element is invalid. Before an XML document can be validated, it must first
be well-formed.
unparsed entity
An external resource referred to by entity reference whose contents may be binary data or text (including
non-XML text). Each unparsed entity has a notation associated with it.
Refers to an XML document that obeys the syntax of XML. A parser cannot parse a document if its XML
is not well-formed. Some of the checks for whether a document is well-formed are:
● Element start tags must have end tags (except for empty elements).
● Attribute values must be quoted.
● Parameter entities must be declared before they are used.
● Markup constructs appear only where permitted.
A more strictly prescribed version of HTML that makes it well-formed XML. XHTML is an official World
Wide Web Consortium recommendation.
An XML query language for locating nodes with an XML tree structure. It allowslocation paths, predicates,
and general expressions in queries. The Cocoa implementation uses XPath 2.0, which is a World Wide
Web Consortium recommendation. The NSXMLNode class enables XPath queries through its
nodesForXPath:error: method. (Note that the NSXML classes do not support deprecated XPath 1.0
features such as namespace axis.)
XML Glossary
2010-03-24 | © 2004, 2010 Apple Inc. All Rights Reserved.
A flexible and powerful XML query language that lets you compose logically complex queries using
operators, quantifiers, functions and FLOWR expressions (referring to the keywords for, let, order
by, where, and return). The NSXMLNode class enables XQuery 1.0 queries through its
objectsForXQuery:error: method
XSLT (Extensible Stylesheet Language Transformations)
An XML application for transforming an XML document into another XML document or into an HTML,
RTF, or plain-text document. The stylesheet used in a transformation has template rules, each consisting
of a pattern and a template. The NSXMLDocument class permits access to XSLT through its
objectByApplyingXSLT:error: and objectByApplyingXSLTAtURL:error: methods.
XML Glossary
2010-03-24 | © 2004, 2010 Apple Inc. All Rights Reserved.
35This table describes the changes to Event-Driven XML Programming Guide .
Date Notes
2010-03-24 Update example code to new initializer pattern.
2008-09-09 Added note about introduction of namespace support in v10.4.
2006-12-05 Added memory management guideline and corrected code examples.
Updated the glossary of XML terms. Changed title from "Event-Driven
XML Parsing." Changed "Rendezvous" to "Bonjour."
Updated the XML glossary to define additional terms primarily related to
the NSXML set of classes. This glossary is shared with Tree-Based XML
Programming Guide .
2004-07-27 Minor bug fix.
2004-01-21 First version of Event-Driven XML Parsing .
2010-03-24 | © 2004, 2010 Apple Inc. All Rights Reserved.
Document Revision HistoryApple Inc.
© 2004, 2010 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrievalsystem, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer for personal use only and to print
copies of documentation for personal use
provided that the documentation contains
Apple's copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-labeled computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
Apple, the Apple logo, Bonjour, Cocoa, Mac, and
OS X are trademarks of Apple Inc., registered in
the U.S. and other countries.
Even though Apple has reviewed this document,
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer,
agent, or employee is authorized to make any
modification, extension, or addition to this warranty.
Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
you specific legal rights, and you may also have other
rights which vary from state to state.
Date and Time
Programming GuideContents
About Dates and Times 5
At a Glance 5
Creating and Using Date Objects to Represent Absolute Points in Time 5
Working with Calendars and Date Components 6
Performing Date and Time Calculations 6
Working with Different Time Zones 6
Special Considerations for Historical Dates 6
How to Use this Document 7
See Also 7
Dates 8
Date Fundamentals 8
Creating Date Objects 9
Basic Date Calculations 10
Calendars, Date Components, and Calendar Units 11
Calendar Basics 11
Date Components and Calendar Units 12
Converting between Dates and Date Components 12
Converting from One Calendar to Another 14
Calendrical Calculations 16
Adding Components to a Date 16
Determining Temporal Differences 18
Checking When a Date Falls 20
Week-Based Calendars 21
Using Time Zones 23
Creating Time Zones 23
Application Default Time Zone 24
Creating Dates with Time Zones 24
Time Zones and Daylight Saving Time 25
Historical Dates 26
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
2The Gregorian Calendar Has No Year 0 26
The Julian to Gregorian Transition 27
Working with Eras with Backward Time Flow 27
Document Revision History 29
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
3Tables and Listings
Dates 8
Listing 1 Creating dates with time intervals 9
Listing 2 Creating dates by adding a time interval 9
Calendars, Date Components, and Calendar Units 11
Listing 3 Creating calendar objects 11
Listing 4 Creating a date components object 12
Listing 5 Getting a date's components 13
Listing 6 Creating a date from components 13
Listing 7 Creating a yearless date 14
Listing 8 Converting date components from one calendar to another 14
Calendrical Calculations 16
Table 1 December 2009 Calendar 21
Table 2 January 2010 Calendar 21
Listing 9 An hour and a half from now 16
Listing 10 Getting the Sunday in the current week 16
Listing 11 Getting the beginning of the week 17
Listing 12 Getting the difference between two dates 18
Listing 13 Days between two dates, as the number of midnights between 19
Listing 14 Days between two dates in different eras 19
Listing 15 Determining whether a date is this week 20
Using Time Zones 23
Listing 16 Creating a date from components using a specific time zone 24
Historical Dates 26
Listing 17 Using negative years to represent BC dates 26
Listing 18 Tomorrow in the BC era 27
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
4Date and time objects allow you to store references to particular instances in time. You can use date and time
objectsto perform calculations and comparisonsthat account for the corner cases of date and time calculations.
At a Glance
There are three main classes used for working with dates and times.
● NSDate allows you to represent an absolute point in time.
● NSCalendar allows you to represent a particular calendar, such as a Gregorian or Hebrew calendar. It
providesthe interface for most date-based calculations and allows you to convert between NSDate objects
and NSDateComponents objects.
● NSDateComponents allows you to represent the components of a particular date, such as hour, minute,
day, year, and so on.
In addition to these classes, NSTimeZone allows you to represent a geopolitical region'stime zone information.
It eases the task of working across different time zones and performing calculations that may be affected by
daylight savings time transitions.
Creating and Using Date Objects to Represent Absolute Points in Time
Date objects represent dates and times in Cocoa. Date objects allow you to store absolute points in time which
are meaningful across locales, calendars and timezones.
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
About Dates and TimesRelevant Chapters: "Dates" (page 8)
Working with Calendars and Date Components
Date components allow you to break a date down into the various parts that comprise it, such as day, month,
year, hour, and so on. Calendars represent a particular form of reckoning time, such as the Gregorian calendar
or the Chinese calendar. Calendar objects allow you to convert between date objects and date component
objects, as well as from one calendar to another.
Relevant Chapters: "Calendars, Date Components, and Calendar Units" (page 11)
Performing Date and Time Calculations
Calendars and date components allow you to perform calculationssuch asthe number of days or hours between
two dates or finding the Sunday in the current week. You can also add components to a date or check when
a date falls.
Relevant Chapters: "Calendrical Calculations" (page 16)
Working with Different Time Zones
Time zone objects allow you to present absolute times as local—that is, wall clock—time. In addition to time
offsets, they also keep track of daylight saving time differences. Proper use of time zone objects can avoid
issues such as miscalculation of elapsed time due to daylight saving time transitions or the user moving to a
different time zone.
Relevant Chapters: "Using Time Zones" (page 23)
Special Considerations for Historical Dates
Dates in the past have a number of edge cases that do not exist for contemporary dates. These include issues
such as datesthat do not exist in a particular calendar—such asthe lack of the year 0 in the Gregorian calendar—
or calendar transitions—such as the Julian to Gregorian transition in the Middle Ages. There are also eras with
seemingly backward time flow—such as BC dates in the Gregorian calendar.
About Dates and Times
At a Glance
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
6Relevant Chapters: "Historical Dates" (page 26)
How to Use this Document
If your application keeps track of dates and times, read from "Dates" (page 8) to "Using Time Zones" (page
23). The NSDate, NSCalendar, NSDateComponents, and NSTimeZone classes described in these chapters
work together to store, compare, and manipulate dates and times.
If your application deals with dates in the past—particularly prior to the early 1900s, also read "Historical
Dates" (page 26) to learn about some of the issues that can arise when dealing with dates in the past.
See Also
If you are new to Cocoa, read:
● Cocoa Fundamentals Guide , which introduces the basic concepts, terminology, architectures, and design
patterns of the Cocoa frameworks and development environment.
If you display dates and times to users or create dates from user input, read:
● Data Formatting Guide , which explains how to create and format user-readable strings from date objects,
and how to create date objects from formatted strings.
About Dates and Times
How to Use this Document
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
7Date objects allow you to represent dates and times in a way that can be used for date calculations and
conversions. As absolute points in time, date objects are meaningful across locales, timezones, and calendars.
Date Fundamentals
Cocoa represents dates and times as NSDate objects. NSDate is one of the fundamental Cocoa value objects.
A date object represents an invariant point in time. Because a date is a point in time, it implies clock time as
well as a day, so there is no way to define a date object to represent a day without a time.
To understand how Cocoa handles dates, you must consider NSCalendar and NSDateComponents objects
as well. In a nontechnical context, a point in time is usually represented by a combination of a clock time and
a day on a particular calendar (such as the Gregorian or Hebrew calendar). Supporting different calendars is
important for localization. In Cocoa, you use a particular calendar to decompose a date object into its date
components such as year, month, day, hour, and minute. Conversely, you can use a calendar to create a date
object from date components. Calendar and date component objects are described in more detail in "Calendars,
Date Components, and Calendar Units" (page 11).
NSDate provides methods for creating dates, comparing dates, and computing intervals. Date objects are
immutable. The standard unit of time for date objects is floating point value typed as NSTimeInterval and
is expressed in seconds. Thistype makes possible a wide and fine-grained range of date and time values, giving
precision within milliseconds for dates 10,000 years apart.
NSDate computes time as seconds relative to an absolute reference time: the first instant of January 1, 2001,
Greenwich Mean Time (GMT). Dates before then are stored as negative numbers; dates after then are stored
as positive numbers. The sole primitive method of NSDate, timeIntervalSinceReferenceDate provides
the basis for all the other methods in the NSDate interface. NSDate converts all date and time representations
to and from NSTimeInterval values that are relative to the absolute reference date.
Cocoa implementstime according to the Network Time Protocol (NTP)standard, which is based on Coordinated
Universal Time.
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
DatesCreating Date Objects
If you want a date that represents the current time, you allocate an NSDate object and initialize it with init:
NSDate *now = [[NSDate alloc] init];
or use the NSDate class method date to create the date object. If you want some time other than the current
time, you can use one of NSDate's initWithTimeInterval... or dateWithTimeInterval... methods;
typically, however, you use a more sophisticated approach employing a calendar and date components as
described in "Calendar Basics" (page 11).
The initWithTimeInterval... methods initialize date objects relative to a particular time, which the
method name describes. You specify (in seconds) how much more recent or how much more in the past you
want your date object to be. To specify a date that occurs earlier than the method's reference date, use a
negative number of seconds.
Listing 1 defines two date objects. The tomorrow object is exactly 24 hours from the current date and time,
and yesterday is exactly 24 hours earlier than the current date and time.
Listing 1 Creating dates with time intervals
NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *tomorrow = [[NSDate alloc]
NSDate *yesterday = [[NSDate alloc]
[tomorrow release];
[yesterday release];
Listing 2 shows how to get new date objects with date-and-time values adjusted from existing date objects
using dateByAddingTimeInterval:.
Listing 2 Creating dates by adding a time interval
NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *today = [[NSDate alloc] init];
NSDate *tomorrow, *yesterday;
tomorrow = [today dateByAddingTimeInterval: secondsPerDay];
Creating Date Objects
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
9yesterday = [today dateByAddingTimeInterval: -secondsPerDay];
[today release];
Basic Date Calculations
To compare dates, you can use the isEqualToDate:, compare:, laterDate:, and earlierDate: methods.
These methods perform exact comparisons, which means they detect sub-second differences between dates.
You may want to compare dates with a less fine granularity. For example, you may want to consider two dates
equal if they are within a minute of each other. If this is the case, use timeIntervalSinceDate: to compare
the two dates. The following code fragmentshows how to use timeIntervalSinceDate: to see if two dates
are within one minute (60 seconds) of each other.
if (fabs([date2 timeIntervalSinceDate:date1]) < 60) ...
To obtain the difference between a date object and another point in time, send a timeIntervalSince...
message to the date object. For example, timeIntervalSinceNow gives you the time, in seconds, between
the current time and the receiving date object.
To get the component elements of a date, such as the day of the week, use an NSDateComponents object in
conjunction with an NSCalendar object. This technique is described in "Calendar Basics" (page 11).
Basic Date Calculations
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
10Calendar objects encapsulate information about systems of reckoning time in which the beginning, length,
and divisions of a year are defined. You use calendar objects to convert between absolute times and date
components such as years, days, or minutes.
Calendar Basics
NSCalendar provides an implementation of various calendars. It provides data for several different calendars,
including Buddhist, Gregorian, Hebrew, Islamic, and Japanese (which calendars are supported depends on the
release of the operating system—check the NSLocale class to determine which are supported on a given
release). NSCalendar is closely associated with the NSDateComponents class, instances of which describe
the component elements of a date required for calendrical computations.
Calendars are specified by constants in NSLocale. You can get the calendar for the user's preferred locale
most easily using the NSCalendar method currentCalendar; you can get the default calendar from any
NSLocale object using the key NSLocaleCalendar. You can also create an arbitrary calendar object by
specifying an identifier for the calendar you want. Listing 3 shows how to create a calendar object for the
Japanese calendar and for the current user.
Listing 3 Creating calendar objects
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSCalendar *japaneseCalendar = [[NSCalendar alloc]
NSCalendar *usersCalendar =
[[NSLocale currentLocale] objectForKey:NSLocaleCalendar];
Here, usersCalendar and currentCalendar are equal, although they are different objects.
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
Calendars, Date Components, and Calendar UnitsDate Components and Calendar Units
You represent the component elements of a date—such as the year, day, and hour—using an
NSDateComponents object. An NSDateComponents object can hold either absolute values or quantities of
units (see "Adding Components to a Date" (page 16) for an example of using NSDateComponents to specify
quantities of units). For date components objects to be meaningful, you need to know the associated calendar
and purpose.
iOS Note: In iOS 4.0 and later, NSDateComponents objects can contain a calendar, a timezone, and
a date object. This allows date components to be passed to or returned from a method and retain
their meaning.
Day, week, weekday, month, and year numbers are generally 1-based, but there may be calendar-specific
exceptions. Ordinal numbers, where they occur, are 1-based. Some calendars may have to map their basic unit
concepts into the year/month/week/day/… nomenclature. The particular values of the unit are defined by
each calendar and are not necessarily consistent with values for that unit in another calendar.
Listing 4 shows how you can create a date components object that you can use to create the date where the
year unit is 2004, the month unit is 5, and the day unit is 6 (in the Gregorian calendar this is May 6th, 2004).
You can also use it to add 2004 year units, 5 month units, and 6 day units to an existing date. The value of
weekday is undefined since it is not otherwise specified.
Listing 4 Creating a date components object
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:6];
[components setMonth:5];
[components setYear:2004];
NSInteger weekday = [components weekday]; // Undefined (== NSUndefinedDateComponent)
Converting between Dates and Date Components
To decompose a date into constituent components, you use the NSCalendar method
components:fromDate:. In addition to the date itself, you need to specify the components to be returned
in the NSDateComponents object. For this, the method takes a bit mask composed of Calendar Units
constants. There is no need to specify any more components than those in which you are interested. Listing
5 shows how to calculate today's day and weekday.
Calendars, Date Components, and Calendar Units
Date Components and Calendar Units
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
12Listing 5 Getting a date's components
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc]
NSDateComponents *weekdayComponents =
[gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit)
NSInteger day = [weekdayComponents day];
NSInteger weekday = [weekdayComponents weekday];
This gives you the absolute components for a date. For example, if you ask for the year and day components
for November 7, 2010, you get 2010 for the year and 7 for the day. If you instead want to know what number
day of the year it is you can use the ordinalityOfUnit:inUnit:forDate: method of the NSCalendar
It is also possible to create a date from components. You can configure an instance of NSDateComponents
to specify the components of a date and then use the NSCalendar method dateFromComponents: to create
the corresponding date object. You can provide as many components as you need (or choose to). When there
is incomplete information to compute an absolute time, default values such as 0 and 1 are usually chosen by
a calendar, but this is a calendar-specific choice. If you provide inconsistent information, calendar-specific
disambiguation is performed (which may involve ignoring one or more of the parameters).
Listing 6 shows how to create a date object to represent (in the Gregorian calendar) the first Monday in May,
Listing 6 Creating a date from components
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setWeekday:2]; // Monday
[components setWeekdayOrdinal:1]; // The first Monday in the month
[components setMonth:5]; // May
[components setYear:2008];
NSCalendar *gregorian = [[NSCalendar alloc]
NSDate *date = [gregorian dateFromComponents:components];
Calendars, Date Components, and Calendar Units
Converting between Dates and Date Components
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
13To guarantee correct behavior you must make sure that the components used make sense for the calendar.
Specifying "out of bounds" components—such as a day value of -6 or February 30th in the Gregorian
calendar—produce undefined behavior.
You may want to create a date object without components such as years—to store your friend's birthday, for
instance. While it is not technically possible to create a yearless date, you can use date components to create
a date object without a specified year, as in Listing 7.
Listing 7 Creating a yearless date
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setMonth:11];
[components setDay:7];
NSCalendar *gregorian = [[NSCalendar alloc]
NSDate *birthday = [gregorian dateFromComponents:components];
Note that birthday in this instance has the default value for the year, which in this case is 1 AD (though it is
not guaranteed to always default to 1 AD). If you later convert this date back to components, or use an
NSDateFormatter object to display it, make sure to not use the year value (as your friend may not appreciate
being listed asthat old). You can use the NSDateFormatter dateFormatFromTemplate:options:locale:
method to create a yearless date formatter that adjusts to the users locale. For more information on date
formatting see Data Formatting Guide .
Converting from One Calendar to Another
To convert components of a date from one calendar to another—for example, from the Gregorian calendar
to the Hebrew calendar—you first create a date object from the components using the first calendar, then you
decompose the date into components using the second calendar. Listing 8 shows how to convert date
components from one calendar to another.
Listing 8 Converting date components from one calendar to another
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
Calendars, Date Components, and Calendar Units
Converting from One Calendar to Another
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
14NSCalendar *gregorian = [[NSCalendar alloc]
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
[gregorian release];
NSCalendar *hebrew = [[NSCalendar alloc]
NSUInteger unitFlags = NSDayCalendarUnit | NSMonthCalendarUnit |
NSDateComponents *components = [hebrew components:unitFlags fromDate:date];
NSInteger day = [components day]; // 15
NSInteger month = [components month]; // 9
NSInteger year = [components year]; // 5764
Calendars, Date Components, and Calendar Units
Converting from One Calendar to Another
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
15NSDate providesthe absolute scale and epoch for dates and times, which can then be rendered into a particular
calendar for calendrical calculations or user display. To perform calendrical calculations, you typically need to
get the component elements of a date, such as the year, the month, and the day. You should use the provided
methods for dealing with calendrical calculations because they take into account corner cases like daylight
savings time starting or ending and leap years.
Adding Components to a Date
You use the dateByAddingComponents:toDate:options: method to add components of a date (such
as hours or months) to an existing date. You can provide as many components as you wish. Listing 9 shows
how to calculate a date an hour and a half in the future.
Listing 9 An hour and a half from now
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc]
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setHour:1];
[offsetComponents setMinute:30];
// Calculate when, according to Tom Lehrer, World War III will end
NSDate *endOfWorldWar3 = [gregorian dateByAddingComponents:offsetComponents
toDate:today options:0];
Components to add can be negative. Listing 10 shows how you can get the Sunday in the current week (using
a Gregorian calendar).
Listing 10 Getting the Sunday in the current week
NSDate *today = [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc]
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
Calendrical CalculationsinitWithCalendarIdentifier:NSGregorianCalendar];
// Get the weekday component of the current date
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit
Create a date components to represent the number of days to subtract from the
current date.
The weekday value for Sunday in the Gregorian calendar is 1, so subtract 1 from
the number of days to subtract from the date in question. (If today is Sunday,
subtract 0 days.)
NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
[componentsToSubtract setDay: 0 - ([weekdayComponents weekday] - 1)];
NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract
toDate:today options:0];
Optional step:
beginningOfWeek now has the same hour, minute, and second as the original date
To normalize to midnight, extract the year, month, and day components and create
a new date from those components.
NSDateComponents *components =
[gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit |
NSDayCalendarUnit) fromDate: beginningOfWeek];
beginningOfWeek = [gregorian dateFromComponents:components];
Sunday is not the beginning of the week in all locales. Listing 11 illustrates how you can calculate the first
moment of the week (as defined by the calendar's locale):
Listing 11 Getting the beginning of the week
NSDate *today = [[NSDate alloc] init];
Calendrical Calculations
Adding Components to a Date
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
17NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
interval:NULL forDate: today];
Determining Temporal Differences
There are a few ways to calculate the amount of time between dates. Depending on the context in which the
calculation is made, the user likely expects different behavior. Whichever calculation you use, it should be clear
to the user how the calculation is being performed. Since Cocoa implementstime according to the NTP standard,
these methods ignore leap seconds in the calculation. You use components:fromDate:toDate:options:
to determine the temporal difference between two dates in units other than seconds (which you can calculate
with the NSDate method timeIntervalSinceDate:). Listing 12 shows how to get the number of months
and days between two dates using a Gregorian calendar.
Listing 12 Getting the difference between two dates
NSDate *startDate = ...;
NSDate *endDate = ...;
NSCalendar *gregorian = [[NSCalendar alloc]
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
toDate:endDate options:0];
NSInteger months = [components month];
NSInteger days = [components day];
This method handles overflow as you may expect. If the fromDate: and toDate: parameters are a year and
3 days apart and you ask for only the days between, it returns an NSDateComponents object with a value of
368 (or 369 in a leap year) for the day component. However, this method truncatesthe results of the calculation
to the smallest unit supplied. For instance, if the fromDate: parameter corresponds to Jan 14, 2010 at 11:30
PM and the toDate: parameter corresponds to Jan 15, 2010 at 8:00 AM, there are only 8.5 hours between the
two dates. If you ask for the number of days, you get 0, because 8.5 hours is less than 1 day. There may be
Calendrical Calculations
Determining Temporal Differences
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
18situations where this should be 1 day. You have to decide which behavior your users expect in a particular
case. If you do need to have a calculation that returns the number of days, calculated by the number of
midnights between the two dates, you can use a category to NSCalendar similar to the one in Listing 13.
Listing 13 Days between two dates, as the number of midnights between
@implementation NSCalendar (MySpecialCalculations)
-(NSInteger)daysWithinEraFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
NSInteger startDay=[self ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:startDate];
NSInteger endDay=[self ordinalityOfUnit:NSDayCalendarUnit
inUnit: NSEraCalendarUnit forDate:endDate];
return endDay-startDay;
This approach works for other calendar units by specifying a different NSCalendarUnit value for the
ordinalityOfUnit: parameter. For example, you can calculate the number of years based on the number
of times Jan 1, 12:00 AM is present between.
Do not use this method for comparing second differences because it overflows NSInteger on 32-bit platforms.
This method is only valid if you stay within the same era (in the Gregorian Calendar this means that both dates
must be AD or both must be BC). If you do need to compare dates across an era boundary you can use something
similar to the category in Listing 14.
Listing 14 Days between two dates in different eras
@implementation NSCalendar (MyOtherMethod)
-(NSInteger) daysFromDate:(NSDate *) startDate toDate:(NSDate *) endDate
NSCalendarUnit units=NSEraCalendarUnit | NSYearCalendarUnit |
NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comp1=[self components:units fromDate:startDate];
NSDateComponents *comp2=[self components:units fromDate endDate];
[comp1 setHour:12];
[comp2 setHour:12];
NSDate *date1=[self dateFromComponents: comp1];
Calendrical Calculations
Determining Temporal Differences
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
19NSDate *date2=[self dateFromComponents: comp2];
return [[self components:NSDayCalendarUnit fromDate:date1 toDate:date2
options:0] day];
This method creates components from the given dates, and then normalizes the time and compares the two
dates. This calculation is more expensive than comparing dates within an era. If you do not need to cross era
boundaries use the technique shown in Listing 13 (page 19) instead.
Checking When a Date Falls
If you need to determine if a date falls within the current week (or any unit for that matter) you can make use
of the NSCalendar method rangeOfUnit:startDate:interval:forDate:. Listing 15 shows a method
that determines if a given date falls within this week. The week in this case is defined as the period between
Sunday at midnight to the following Saturday just before midnight (in the Gregorian calendar).
Listing 15 Determining whether a date is this week
-(BOOL)isDateThisWeek:(NSDate *)date {
NSDate *start;
NSTimeInterval extends;
NSCalendar *cal=[NSCalendar autoupdatingCurrentCalendar];
NSDate *today=[NSDate date];
BOOL success= [cal rangeOfUnit:NSWeekCalendarUnit startDate:&start
interval: &extends forDate:today];
if(!success)return NO;
NSTimeInterval dateInSecs = [date timeIntervalSinceReferenceDate];
NSTimeInterval dayStartInSecs= [start timeIntervalSinceReferenceDate];
if(dateInSecs > dayStartInSecs && dateInSecs < (dayStartInSecs+extends)){
return YES;
else {
return NO;
Calendrical Calculations
Checking When a Date Falls
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
This code uses NSTimeInterval values for the date to test and the start of the week and uses those to
determine whether the date is this week.
Week-Based Calendars
A week-based calendar is defined by the weeks of a year. However, this can be complicated when the first
week of the calendar overlapsthe last week of the previous year's calendar. In this case there are two important
properties of the calendar:
1. What is the first day of the week?
2. How many days does a week near the beginning of the year have to have within the ordinary calendar
year for it to be considered the first week in the week-based calendar year?
A week-based calendar's first day of the year is on the first day of the week. The first week is preferred to be
the week containing Jan 1 if that week satisfies the defined answer for the second point above.
For example, suppose the first day of the week is defined as Monday, in a week-based calendar interpretation
of the Gregorian calendar. Consider the 2009/2010 transition shown in Table 1 and Table 2:
Table 1 December 2009 Calendar
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
20 21 22 23 24 25 26
27 28 29 30 31
Table 2 January 2010 Calendar
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
Since the first day of the week is Monday, the 2010 week-based calendar year can begin either December 28
or January 4. That is, December 30, 2009 (ordinary) could be December 30, 2010 (week-based).
Calendrical Calculations
Week-Based Calendars
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
21To choose between these two possibilities, there is the second criterion. Week Dec 28 - Jan 3 has 3 days in
2010. Week Jan 4-Jan 10 has 7 days in 2010.
If the minimum number of days in a first week is defined as 1 or 2 or 3, the week of Dec 28 satisfies the first
week criteria and would be week 1 of the week-based calendar year 2010. Otherwise, the week of Jan 4 is the
first week.
As another example,suppose you wanted to define your week-based calendarscheme such that the first week
of the week-based calendar year is the week beginning with the first occurrence of the first day of the week
in the ordinary calendar year. Another way to put that is that you always want the first week of the week-based
calendar year to be within the new ordinary calendar year, you never want your week-based calendar to start
back in December of the previous ordinary year as discussed in the previous example. Or, you always want
your week based calendar to start on Jan 1 or later.
In Table 2 (page 21) Monday January 4 is the first Monday of the ordinary year, so the week-based calendar
begins on that day. What you are requesting then is that the first week of your week-based calendar is entirely
within the new ordinary year or that the minimum number of days in first week is 7.
The NSYearForWeekOfYearCalendarUnit is the year number of a week-based calendar interpretation of
the calendar you're working with, where the two properties of the week-based calendar discussed in above
correspond to these two NSCalendar properties: firstWeekday and minimumDaysInFirstWeek.
Calendrical Calculations
Week-Based Calendars
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
22Time zones can create numerous problems for applications. Consider the following situation. You are in New
York and it is 12:30 AM. You have an application that displays all of the Major League Baseball games that
happen tomorrow. Because tomorrow is different depending on the time zone, situations like this must be
carefully accounted for. Fortunately, a little planning and the assistance of the NSTimeZone class ease this
task considerably.
NSTimeZone is an abstract class that defines the behavior of time zone objects. Time zone objects represent
geopolitical regions. Consequently, these objects have region names. Time zone objects also represent a
temporal offset, either plus or minus, from Greenwich Mean Time (GMT) and an abbreviation (such as PST).
Creating Time Zones
Time zones affect the values of date components that are calculated by calendar objects for a given NSDate
object. You can create an NSTimeZone object and use it to set the time zone of an NSCalendar object. By
default, NSCalendar uses the default time zone for the application—or process—when the calendar object
is created. Unless the default time zone has been otherwise set, it is the time zone set in System Preferences.
In most cases, the user's default time zone should be used when creating date objects. There are cases when
it may be necessary to use arbitrary time zones. For example, the user may want to specify that an appointment
is in Greenwich Mean Time, because it is during her business trip to London next week. NSTimeZone provides
several class methods to make time zone objects: timeZoneWithName:, timeZoneWithAbbreviation:,
and timeZoneForSecondsFromGMT:. In most cases timeZoneWithName: provides the most accurate time
zone, as it adjusts for daylight saving time, the trade-off is that you must know more precisely the location you
are creating a time zone for.
For a complete list of time zone names known to the system, you can use the knownTimeZoneNames class
NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames];
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
Using Time ZonesApplication Default Time Zone
You can set the default time zone within your application using setDefaultTimeZone:. You can access this
default time zone at any time with the defaultTimeZone class method. With the localTimeZone class
method you can get a time zone object that automatically updates itself to reflect changes to the default time
Creating Dates with Time Zones
Time zones play an important part in determining when datestake place. Consider a simple calendar application
that keeps track of appointments. For example, say you live in Chicago and you have a dentist appointment
coming up at 10:00 AM on Tuesday. You will be in New York for Sunday and Monday, however. When you
created that appointment it was done with the mindset of an absolute time. That time is 10:00 AM Central
Time; when you go to New York, the time should be presented as 11:00 AM because you are in a different time
zone, but it isthe same absolute time. On the other hand, if you create an appointment to wake up and exercise
every morning at 7:00 AM, you do not want your alarm to go off at 1:00 PM simply because you are on a
business trip to Dublin—or at 5:00 AM because you are in Los Angeles.
NSDate objects store dates in absolute time. For example, the date object created in Listing 16 represents
4:00 PM CDT, 5:00 EDT, and so on.
Listing 16 Creating a date from components using a specific time zone
NSCalendar *gregorian=[[NSCalendar alloc] initWithCalendarIdentifier:
[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"CDT"]];
NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init];
[timeZoneComps setHour:16];
//specify whatever day, month, and year is appropriate
NSDate *date=[gregorian dateFromComponents:timeZoneComps];
If you need to create a date that isindependent of timezone, you can store the date as an NSDateComponents
object—as long as you store some reference to the corresponding calendar.
In iOS, NSDateComponents objects can contain a calendar, a timezone, and a date object. You can therefore
store the calendar along with the components. If you use the date method of the NSDateComponents class
to access the date, make sure that the associated timezone is up-to-date.
Using Time Zones
Application Default Time Zone
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
24Time Zones and Daylight Saving Time
The NSTimeZone class also provides a number of instance methods to determine information about daylight
saving time:
● isDaylightSavingTime determines whether daylight saving time is currently in effect.
● daylightSavingTimeOffset determines the current daylight saving time offset. For most time zones
this is either zero or one.
● nextDaylightSavingTimeTransition determines when the next daylight saving time transition
There are also similarly named methods for determining this information for specific dates. If you are keeping
track of events and appointments in your application, you can use this information to remind the user of
upcoming daylight saving time transitions.
Using Time Zones
Time Zones and Daylight Saving Time
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
25There are a number of issues that can arise when dealing with dates in the past that do not exist for
contemporary dates. These include dates that do not exist, previous eras where time flow moves from higher
year numbers to lower ones (such as BC dates in the Gregorian calendar), and calendar transitions (such as the
transition from the Julian calendar to the Gregorian calendar).
The Gregorian Calendar Has No Year 0
In the Julian and Gregorian calendars represented by the NSGregorianCalendar, there is no year 0. This
means that the day following December 31, 1 BC is January 1, 1 AD. All of the provided methods for calendrical
calculations take this into account, but you may need to account for it when you are creating dates from
components. If you do attempt to create a date with year 0, it is instead 1 BC. In addition, if you create a date
from components using a negative year value, it is created using astronomical year numbering in which 0
corresponds to 1 BC, -1 corresponds to 2 BC, and so on. For example, the two dates created in Listing
17equivalently represent May 7, 8 BC.
Listing 17 Using negative years to represent BC dates
NSCalendar *gregorian=[[NSCalendar alloc]
NSDateComponents *bcDateComp=[[NSDateComponents alloc] init];
[bcDate setMonth: 5];
[bcDate setDay: 7];
[bcDate setYear: 8];
[bcDate setEra: 0];
NSDateComponents *astronDateComp=[[NSDateComponents alloc] init];
[bcDate setMonth: 5];
[bcDate setDay: 7];
[bcDate setYear: -7];
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
Historical DatesNSDate *bcDate=[gregorian dateFromComponents:bcDateComp];
NSDate *astronDate=[gregorian dateFromComponents:astronDateComp];
The Julian to Gregorian Transition
NSCalendar modelsthe transition from the Julian to Gregorian calendar in October 1582. During thistransition,
10 days were skipped. This means that October 15, 1582 follows October 4, 1582. All of the provided methods
for calendrical calculations take this into account, but you may need to account for it when you are creating
dates from components. Dates created in the gap are pushed forward by 10 days. For example October 8, 1582
is stored as October 18, 1582.
Some countries adopted the Gregorian calendar at variouslater times. Nevertheless, for consistency the change
is modeled at the same time regardless of locale. If you need absolute historical accuracy for a particular locale,
you can subtract the appropriate number of days from the date given by the Gregorian calendar. The number
of days to subtract corresponds to the number of extra leap days in the Julian calendar. Thus for every 100th
year, the Julian calendar falls behind a day if that year is not a multiple of 400. If you need to create a Julian
date, you must subtract the correct number of days from a Gregorian date (10 in the 1500s and 1600s, 11 in
the 1700s, 12 in the 1800s, 13 in the 1900s and 2000s, and so on). You must also take into account the existence
of leap days that aren't in the Gregorian calendar.
Working with Eras with Backward Time Flow
In the Gregorian calendar, time is divided into two eras, the BC era and the AD era. In the BC era, time flows
in a direction seemingly backwards, that is from higher year numbers to lower. However, days and months
flow in the normal direction. For example February 1 follows January 31. This can be confusing if you ask what
day follows December 31, 7 BC. The correct answer is January 1, 6 BC. This example is illustrated in Listing 18.
Listing 18 Tomorrow in the BC era
NSCalendar *gregorian=[[NSCalendar alloc]
initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *dateBCComps=[[NSDateComponents alloc] init];
[dateBCComps setEra:0]; //Era 0 corresponds to BC
[dateBCComps setMonth:12];
[dateBCComps setDay:31];
[dateBCComps setYear:7];
Historical Dates
The Julian to Gregorian Transition
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
27NSDate *dateBC=[gregorian dateFromComponents:dateBCComps];
NSDateComponents *offsetDate=[[NSDateComponents alloc] init];
[offsetDate setDay:1];
NSDate *dateBC2=[gregorian dateByAddingComponents: offsetDate toDate:dateBC
After this code executes dateBC2 corresponds to January 1, 6 BC.
Historical Dates
Working with Eras with Backward Time Flow
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
28This table describes the changes to Date and Time Programming Guide .
Date Notes
Expanded Calendrical Calculationssection. Added Historical Dates Section
and Week-Based Year Section.
2010-02-24 Corrected code snippet.
2009-07-21 Added links to Cocoa Core Competencies.
Moved information about NSCalendarDate to an appendix, rewrote articles
to replace references to NSCalendarDate, and expanded content.
Added a section about how to get date components using NSCalendar
and NSDateComponents and a section about how to convert from one
calendar to another.
Removed information about converting a date to a string. See
NSDateFormatter Class Reference for that information.
2007-09-04 Enhanced discussion of calendrical calculations using NSDateComponents.
2007-03-06 Added note regarding Julian and Gregorian calendars.
Corrected typographical errors. Added a note about the use of width
specifiers for calendar date format strings.
Updated to include NSCalendar and NSDateFormatter changesintroduced
in OS X v10.4.
2005-08-11 Changed title from "Dates and Times." Corrected minor typographic error.
Revision history was added to existing document. It will be used to record
changes to the content of the document.
2011-06-06 | © 2002, 2011 Apple Inc. All Rights Reserved.
Document Revision HistoryApple Inc.
© 2002, 2011 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrievalsystem, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer for personal use only and to print
copies of documentation for personal use
provided that the documentation contains
Apple's copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-labeled computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
Apple, the Apple logo, Chicago, Cocoa, Mac, New
York, Numbers, andOS X are trademarks of Apple
Inc., registered in the U.S. and other countries.
Times is a registered trademark of Heidelberger
Druckmaschinen AG, available from Linotype
Library GmbH.
iOS is a trademark or registered trademark of
Cisco in the U.S. and other countries and is used
under license.
Even though Apple has reviewed this document,
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer,
agent, or employee is authorized to make any
modification, extension, or addition to this warranty.
Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
you specific legal rights, and you may also have other
rights which vary from state to state.
Window Programming
Introduction 6
Organization of This Document 6
See Also 8
How Windows Work 9
How a Window is Displayed 11
How Modal Windows Work 12
How Panels Work 14
How Window Controllers Work 15
Window Closing Behavior 16
Opening and Closing Windows 17
Window Layering and Types of Windows 18
Window Layering 18
Key and Main Windows 19
The Key Window 20
The Main Window 20
Changing a Window's Status 21
Window Layers and Levels 22
Window Levels 22
Setting Ordering and Level Programmatically 22
Setting Window Collection Behavior 24
Spaces Collection Behavior 24
Exposé Collection Behavior 24
Window Cycling Behavior 25
Sizing and Placing Windows 26
Setting a Window's Size and Location 26
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
2Window Cascading 27
Window Zooming 27
Constraining a Window's Size and Location 27
Saving a Window's Position into the User's Defaults 29
Minimizing Windows 30
Using the Window Menu 31
Setting a Window's Appearance 32
Setting a Window's Style 32
Setting a Window's Color and Transparency 33
Setting a Window's Color Space 33
Setting a Window's Content Border Thickness 33
Setting a Window's Title and Represented File 34
Setting Attributes for the Window's Image 35
Specifying How To Store the Window's Image 35
Specifying Where To Store the Window's Image 36
Specifying When the Window's Image Is Created 36
Specifying Whether the Window's Image Persists When Offscreen 37
Specifying the Depth Limit for the Window's Image 37
Specifying Whether the Depth Limit Changes to the Screen's Capacity 37
Specifying Whether Window Content Can Be Read or Written by Another Process 37
Handling Events in Windows 38
Using Keyboard Interface Control in Windows 39
Using the Window's Field Editor 40
Using Window Notifications and Delegate Methods 41
Dragging Images to and from Windows 42
Updating the Cursor Image in a Window 43
Caching Window Images 44
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
3Document Revision History 45
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
4Figures and Listings
Window Layering and Types of Windows 18
Figure 1 Main, key, and inactive windows 19
Saving a Window's Position into the User's Defaults 29
Listing 1 Saving a window's frame automatically 29
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
5An application displays windows on the screen that must be managed and coordinated. A window object
corresponds to at most one on-screen window. The two principal functions of windows are to provide an area
in which views can be placed and to accept and distribute events the user sends through actions with the
mouse and keyboard. The term window sometimes refers to the Application Kit object and sometimes to the
window server's window device; which meaning is intended is made clear in context. Panels are a special kind
of window, typically serving an auxiliary function in an application, such as utility windows.
This document is intended for Cocoa developers who need to work with windows and panels in their
Organization of This Document
This programming topic describes how to use windows and panels. These articles give you basic information
on the different types of windows and how they work:
"How Windows Work" (page 9) describes the classes that define objects that manage and coordinate
the windows an application displays.
"How a Window is Displayed" (page 11) describes how window drawing is accomplished.
"How Modal Windows Work" (page 12) describes the behavior of modal windows.
"How Panels Work" (page 14) describes the various uses of panels.
"How Window Controllers Work" (page 15) describesthe relationship between a window and its controller.
"Window Layering and Types of Windows" (page 18) describes window layering and the concepts of key
and main windows, and how a window can avoid becoming key or main.
"Window Layers and Levels" (page 22) describes window levels, and how to place a window in a specific
level, such as the level for document windows, palettes, or tear-off menus.
"Setting Window Collection Behavior" (page 24) describes how to set a window's behavior with Spaces,
Exposé, and window cycles.
These articles describe how to use windows:
"Opening and Closing Windows" (page 17) describes how to open and close, or just show and hide, a
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
"Sizing and Placing Windows" (page 26) describes how to control a window's size and position, including
how to set its minimum and maximum size, how to constrain it to the screen, how to cascade it so its title
bar remains visible, how to zoom it as though the user pressed the zoom button, and how to center it on
the screen.
"Saving a Window's Position into the User's Defaults" (page 29) describes how to store a window's position
in the user defaults system, so that it appears in the same location the next time the user starts the
"Minimizing Windows" (page 30) describes how to replace a window with a smaller counterpart in the
"Using the Window Menu" (page 31) describes how to place a window's name in the Windows menu that
appears in most Cocoa applications.
These articles describe how to change what a window looks like:
"Setting a Window's Appearance" (page 32) describes how to choose whether to display a window's
peripheral elements, including its title bar, close box, zoom box, or size box. It also describes how to set
a window's background color and transparency,
"Setting a Window's Title and Represented File" (page 34) describes how to set a window's title with either
a string or the filename of the window's represented file.
"Setting Attributes for the Window's Image" (page 35) describes how to set attributes for the window's
device, which stores the window's image, including how the image is stored, when the image is created,
and the image's color depth.
These articles describe how to handle a window's events:
"Handling Events in Windows" (page 38) gives basic information on how a window handles events.
"Using Keyboard Interface Control in Windows" (page 39) describes how to navigate between a window's
fields using the Tab key and how to use the Return and Escape keys to select default buttons.
"Using the Window's Field Editor" (page 40) describes how to use the window's text object, which is
shared for light editing tasks.
These articles describe some advanced features of windows:
"Using Window Notifications and Delegate Methods" (page 41) describes the notifications and delegate
methods used when a window gains or loses key or main window status, minimizes, moves or resizes,
becomes exposed, or closes.
"Dragging Images to and from Windows" (page 42) describes what happens when the user wants to drag
an object into or out of a window.
Organization of This Document
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
"Updating the Cursor Image in a Window" (page 43) directs you to information on how to change the
cursor image when the cursor is over a specified area in a view.
"Caching Window Images" (page 44) describes how to temporarily cache a portion of a window's image
so that it can be restored later. Thisis useful when highly dynamic drawing must be done over an otherwise
static image of the window.
See Also
For additional information on specific types of windows and panels, you can also see the following programming
● Sheet Programming Topics describes a dialog attached to a specific window, ensuring that a user never
loses track of which window the dialog belongs to.
● Drawer Programming Topics describes a type of view that slides out from one side of a window.
● Toolbar Programming Topics for Cocoa describes a standard way to display a toolbar for a titled window
below its title bar and provide users with a way to customize toolbars and save those customizations.
● Dialogs and Special Panels describes alert panels and other specialized types of panels, such as Font, Save,
and Print panels.
● Document-Based App Programming Guide for Mac describes how to use the architecture supplied by
AppKit to create applications that can create, open, load, and save multiple document files.
● Cocoa Event Handling Guide discusses the variety of ways your application objects can handle the events
they receive.
See Also
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
8The NSWindow class defines objects that manage and coordinate the windows an application displays on the
screen. A single NSWindow object corresponds to at most one onscreen window. The two principal functions
of an NSWindow object are to provide an area in which NSView objects can be placed and to accept and
distribute, to the appropriate views, events the user instigates through actions with the mouse and keyboard.
Note that the term window sometimes refers to the Application Kit object and sometimes to the window
server's display device; which meaning is intended is made clear in context. AppKit also defines an abstract
subclass of NSWindow—NSPanel—that adds behavior more appropriate for auxiliary windows.
An NSWindow object is defined by a frame rectangle that encloses the entire window, including its title bar,
border, and other peripheral elements (such as the resize control), and by a content rectangle that encloses
just its content area. Both rectangles are specified in the screen coordinate system and are restricted to integer
values. The frame rectangle establishesthe window's base coordinate system. This coordinate system is always
aligned with and measured in the same increments as the screen coordinate system (in other words, the base
coordinate system can't be rotated or scaled). The origin of the base coordinate system is the bottom-left
corner of the window's frame rectangle.
Typically, you create windows using Interface Builder, which allows you to position them, set many of their
attributes, and lay out their views. The programmatic work you do with windows more often involves bringing
them on and off the screen; changing dynamic attributes such as the window's title; running modal windows
to restrict user input; and assigning a delegate that can monitor certain of the window's actions,such as closing,
zooming, and resizing.
You can also create a window programmatically with one of itsinitializers by specifying, among other attributes,
the size and location of its content rectangle. The frame rectangle is derived from the dimensions of the content
When it's created, a window automatically createstwo views: an opaque frame view that fillsthe frame rectangle
and draws the border, title bar, other peripheral elements, and background, and a transparent content view
that fills the content rectangle. The frame view and its peripheral elements are private objects that your
application can't access directly. The content view is the "highest" accessible view in the window; you can
replace the default content view with a view of your own creation using the setContentView: method. The
window determines the placement of the content view; you can't position it using the NSView methods that
begin with setFrame; you must use the NSWindow class's placement methods, as described in "Opening and
Closing Windows" (page 17).
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
How Windows WorkYou add other views to the window as subviews of the content view or as subviews of any of the content
view's subviews, and so on, via the addSubview: method of NSView. This tree of views is called the window's
view hierarchy. When a window is told to display itself, it does so by sending display... messages to the
top-level view in its view hierarchy. Because displaying is carried out in a determined order, the content view
(which is drawn first) may be wholly or partially obscured by itssubviews, and these subviews may be obscured
by their subviews (and so on).
How Windows Work
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
10Displaying an NSWindow object begins with the drawing performed by its view objects, which accumulates
in the window's display buffer or appears immediately on the screen. Windows, like NSView objects, can be
displayed unconditionally or merely marked as needing display, using the display and
setViewsNeedDisplay: methods, respectively. A displayIfNeeded message causes the window's views
to display only if they've been marked as needing display. Normally, any time a view is marked as needing
display, the window makes note of this fact and automatically displays itself shortly thereafter. This automatic
display is typically performed on each pass through the event loop, but can be turned off using the
setAutodisplay: method. If you turn off autodisplay for a window, you're then responsible for displaying
it whenever necessary.
A window's views can be drawn concurrently. You can use the methods allowsConcurrentViewDrawing
and setAllowsConcurrentViewDrawing: to determine and set, respectively, whether or not a window
draws its views concurrently. By default, a window's views are drawn concurrently.
On each passthrough the event loop, the application object invokesits updateWindows method, which sends
an update message to each window. Subclasses of NSWindow can override this method to examine the state
of the application and change their own state or appearance accordingly—enabling or disabling menus,
buttons, and other controls based on the object that's selected, for example.
In addition to displaying itself on the screen, a window can print itself in its entirety, just as a view can. The
print: method runs the application's Print panel and causes the window's frame view to print itself.
dataWithEPSInsideRect: behaves similarly. For additional information see Printing Programming Guide
for OS X .
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
How a Window is DisplayedYou can make a whole window or panel run in application-modal fashion, using the application's normal event
loop machinery but restricting input to the modal window or panel. Modal operation is useful for windows
and panels that require the user's attention before an action can proceed. Examples include error messages
and warnings, as well as operations that require input, such as open dialogs, or dialogs that apply to multiple
There are two mechanisms for operating an application-modal window or panel. The first, and simpler, is to
invoke the runModalForWindow: method of NSApplication, which monopolizes events for the specified
window until one of stopModal, abortModal, or stopModalWithCode: is invoked, typically by a button's
action method. The stopModal method ends the modal status of the window or panel from within the event
loop. It doesn't work if invoked from a method invoked by a timer or by a distributed object because those
mechanisms operate outside of the event loop. To terminate the modal loop in these situations, you can use
abortModal. The stopModal method is typically invoked when the user clicks the OK button (or equivalent),
abortModal when the user clicks the Cancel button (or presses the Escape key). These two methods are
equivalent to stopModalWithCode: with the appropriate argument.
The second mechanism for operating a modal window or panel, called a modal session, allowsthe application
to perform a long operation while it still sends events to the window or panel. Modal sessions are particularly
useful for panels that allow the user to cancel or modify an operation. To begin a modal session, invoke
beginModalSessionForWindow: on the application, which sets the window up for the session and returns
an identifier used for other session-controlling methods. At this point, the application can run in a loop that
performsthe operation, invoking runModalSession: on the application object on each passso that pending
events can be dispatched to the modal window. This method returns a code indicating whether the operation
should continue, stop, or abort, which is typically established by the methods described above for
runModalForWindow:. After the loop concludes, you can remove the window from the screen and invoke
endModalSession: on the application to restore the normal event loop.
Note: You can write a modal event loop for a view object so that the object has access to all events
pertaining to a particular task, such as tracking the mouse in the view. For an example, see
"Responding to User Events and Actions" in "Creating a Custom View".
The normal behavior of a modal window or session is to exclude all other windows and panels from receiving
events. For windows and panels that serve as general auxiliary controls, such as menus and the Font panel,
this behavior is overly restrictive. The user must be able to use menu key equivalents (such as those for Cut
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
How Modal Windows Workand for Paste) and change the font of text in the modal window, and this requires that non-modal panels be
able to receive events. To support this behavior, an NSWindow subclass overridesthe worksWhenModal method
to return YES. This allows the window to receive mouse and keyboard events even when a modal window is
present. If a subclass needs to work when a modal window is present, it should generally be a subclass of
NSPanel, not of NSWindow.
Modal windows and modal sessions provide different levels of control to the application and the user. Modal
windows restrict all action to the window itself and any methods invoked from the window. Modal sessions
allow the application to continue an operation while accepting input only through the modal session window.
Beyond this, you can use distributed objects to perform background operations in a separate thread, while
allowing the user to perform other actions with any part of the application. The background thread can
communicate with the main thread, allowing the application to display the status of the operation in a
non-modal panel, perhaps including controls to stop or affect the operation as it occurs. Note that because
AppKit isn't thread-safe, the background thread should communicate with a designated object in the main
thread that in turn interacts with the AppKit.
Before OS X version 10.6, if a modal window was open, application termination would be prevented if the user
attempted to terminate that window's application. Beginning in OS X version 10.6, you can call
setPreventsApplicationTerminationWhenModal: with a value of NO, and the window will not prevent
application termination when modal. The current value of this property may be accessed by calling
preventsApplicationTerminationWhenModal. The default value is NO.
How Modal Windows Work
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
13A panel is a special kind of window, typically serving an auxiliary function in an application. The NSPanel
subclass of NSWindow adds a few special behaviors to windows in support of the role panels play:
● By default panels are not released when they're closed, because they're usually lightweight and often
● Onscreen panels, except for alert dialogs, are removed from the screen when the application isn't active
and are restored when the application again becomes active. This reduces screen clutter.
Specifically, the NSWindow implementation of the hidesOnDeactivate method returns NO, but the
NSPanel implementation of the same method returns YES.
● Panels can become the key window, but they cannot become the main window.
If a panel is the key window and has a close button, it closes itself when the user presses the Escape key.
In addition to these automatic behaviors, the NSPanel class allows you to configure certain other behaviors
common to some kinds of panels:
● You can prevent a panel from becoming the key window unless the user clicks in a view that responds to
typing. This prevents the key window from shifting to the panel unnecessarily. The
setBecomesKeyOnlyIfNeeded: method controls this behavior.
● Palettes and similar panels can be made to float above standard windows and other panels. This prevents
them from being covered and keepsthem readily available to the user. The setFloatingPanel: method
controls this behavior.
● A panel can be made to receive mouse and keyboard events even when another window or panel is being
run modally or in a modal session. This permits actions in the panel to affect the modal window or panel.
The setWorksWhenModal: method controls this behavior. See "How Modal Windows Work" (page 12)
for more information on modal windows and panels.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
How Panels WorkA controller object (in this case, an instance of the NSWindowController class) manages a window; this object
is usually stored in a nib file. This management entails the following:
● Loading and displaying the window
● Closing the window when appropriate
● Customizing the window's title
● Storing the window's frame (size and location) in the defaults database
● Cascading the window in relation to other document windows of the application
A window controller can manage a window by itself or as a participant in AppKit's document-based architecture,
which also includes the NSDocument and NSDocumentController classes. In this architecture, a window
controller is created and managed by a document (an instance of an NSDocument subclass) and, in turn, keeps
a reference to the document. For a discussion of this architecture, see Document-Based App Programming
Guide for Mac .
The relationship between a window controller and a nib file is important. Although a window controller can
manage a programmatically created window, it usually manages a window in a nib file. The nib file can contain
other top-level objects, including other windows, but the window controller's responsibility is this primary
window. The window controller is usually the owner of the nib file, even when it is part of a document-based
For simple documents—that is, documents with only one nib file containing a window—you need do little
directly with NSWindowController objects. AppKit creates one for you. However, if the default window
controller is not sufficient, you can create a custom subclass of NSWindowController.
For documents with multiple windows or panels, your document must create separate instances of
NSWindowController (or of custom subclasses of NSWindowController), one for each window or panel.
An example is a CAD application that has different windows for side, top, and front views of drawn objects.
What you do in your NSDocument subclass determines whether the default NSWindowController object or
separately created and configured NSWindowController objects are used.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
How Window Controllers WorkWindow Closing Behavior
When a window is closed and it is part of a document-based application, the document removes the window's
window controller from itslist of window controllers. Thisresultsin the system deallocating the window controller
and the window, and possibly the NSDocument object itself. When a window controller is not part of a
document-based application, closing the window does not by default result in the deallocation of the window
or window controller. This is the desired behavior for a window controller that manages something like an
inspector; you shouldn't have to load the nib file again and re-create the objectsthe next time the user requests
the inspector.
If you want the closing of a window to make both window and window controller go away when it isn't part
of a document, yoursubclass of NSWindowController can observe the NSWindowWillCloseNotification
notification or, as the window delegate, implement the windowWillClose: method.
How Window Controllers Work
Window Closing Behavior
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
16This article describes how to open and close a window.
Opening a window—that is, making a window visible—is normally accomplished by placing the window into
the application's window list by invoking one of the methods makeKeyAndOrderFront:, orderFront:, etc.,
in NSWindow, and so on. Also, with certain bits set in Interface Builder, the window is shown when the nib file
is loaded in some cases.
Closing a window involves explicit use of either the close method, which simply removes the window from
the screen, or performClose:, which highlights the close button as though the user clicked it. Closing a
window involves at least removing it from the screen but may include disposing of it altogether. The
setReleasedWhenClosed: method specifies whether a window releases itself when it receives a close
message. A window's delegate is also notified when it's about to close, as described in "Using Window
Notifications and Delegate Methods" (page 41).
These methods hide a window without closing it. The method orderOut: removes a window from the screen.
You can also set a window to be removed from the screen automatically when its application isn't active using
setHidesOnDeactivate:. The isVisible method returns whether a window is on or off the screen.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Opening and Closing WindowsEach window is placed on the screen by a particular application, and each application typically owns a variety
of windows. Windows have numerous characteristics. They can be located onscreen or offscreen. Onscreen
windows are placed on the screen in levels managed by the window server.
Windows onscreen are ordered from front to back. Like sheets of paper loosely stacked together, windows in
front can overlap, or even completely cover, those behind them. Each window has a unique position in the
order. When two windows are placed side-by-side, one is still technically in front of the other.
If any window could be in front of any other window, then small but important windows—like menus and
tool palettes—might get lost behind larger ones. Windows that require user action, like attention panels and
pop-up lists, might disappear behind another window and go unnoticed. To prevent this, all the windows
onscreen are organized into levels.
When two windows belong to the same level, either one can be in front. When two windows belong to different
levels, however, the one in the higher level will always be above the other.
Onscreen windows can also carry a status: main or key . Offscreen windows are hidden or minimized on Dock,
and do not carry either status. Onscreen windows that are neither main nor key are inactive.
Window Layering
Each application and document window exists in its own layer, so documents from different applications can
be interleaved. Clicking a window to bring it to the front doesn't disturb the layering order of any other window.
A window's depth in the layers is determined by when the window was last accessed. When a user clicks an
inactive document or chooses it from the Window menu, only that document, and any open utility windows,
should be brought to the front. Users can bring all windows of an application forward by clicking its icon in
the Dock or by choosing Bring All to Front in the application's Window menu. These actions should bring
forward all of the application's open windows, maintaining their onscreen location, size, and layering order
within the application. For more information, see "UI Element Guidelines: Menus" in OS X Human Interface
Utility windows are alwaysin the same layer: the top layer. They are visible only when their application is active.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Window Layering and Types of WindowsKey and Main Windows
Windows have different looks based on how the user is interacting with them. The foremost document or
application window that is the focus of the user's attention is referred to as the main window. Each application
also has only one main window at a given time. This main window often has key status, as well. The main
window is the principal focus of user actions for an application. Often, user actions in a modal key window
(typically a panel such as the Font window or an Info window) have a direct effect on the main window.
Main and key windows are both active windows. Active windows are visually distinct from inactive windows
in that their controls have color, while the controls in inactive windows do not have color. Inactive windows
are windows the user has open but that are not in the foreground. Main and key windows are always in the
foreground and their controls always have color. If the main and key window are different windows, they are
distinguished from one another by the look of their title bars. Note the visual distinctions between main, key,
and inactive windows in Figure 1.
Figure 1 Main, key, and inactive windows
Inactive window
Main window
Key window
A good example of the difference between key and main windows can be seen in most well-behaved Mac
apps. Selecting "Save As..." in a text document, for example, displays a panel with a field to type the document's
name and a pull-down menu of locations to save it. The panel represents the key window. It will accept your
Window Layering and Types of Windows
Key and Main Windows
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
19keyboard input (the file name), but will directly affect the main window under it (by saving it to the location
you specified). Once you save the document, the save panel disappears, the main window becomes key again,
and will accept keyboard input once more.
The Key Window
The key window responds to user input, whether from the keyboard, mouse, or alternative input devices, for
an application and is the primary recipient of messages from menus and panels. Usually, a window is made
key when the user clicks it. Each application can have only one key window at a given time.
Users expect to see their actions on the keyboard and mouse take effect not only in a particular application,
but also in a particular window of that application. Each user action is associated with a window by the window
server and AppKit. Before acting, the user needs to know which window will be affected; there should be no
Since the mouse controls the pointer, it's quite easy for the user to determine which window a mouse action
is associated with. It's whatever window the pointer is over. But the keyboard doesn't have a pointer, so there's
no natural way to determine where typed characters will appear.
To mark the key window for users, AppKit highlights its title bar. You can think of the highlighting as a kind
of pointer for the keyboard. It shifts from window to window as the key window changes. Key-window status
also moves from application to application as the active application changes. Only one window on the screen
is marked at a time, and it is in the active application. There's just one key window on the Desktop. Even a
system that has two screens, but only one keyboard, has at most one key window.
Note: A window doesn't have to become the key window to receive, and act on, keyboard shortcuts.
It does, however, have to be a window in the active application.
Since the key window belongs to the active application, its highlighted title bar has the secondary effect of
helping to show which application is currently active. The key window isthe most prominently marked window
in the active application, making it "key" in a second sense: it's the main focus of the user's attention on the
The Main Window
The main window is the standard window where the user is currently working. The main window is not always
the key window. There are times when a window other than the main window takes the focus of the input
device, while the main window still remains the focus of the user's attention and of user actions carried out in
panels and menus. For example, when a person is using an inspector, a Find dialog, or the Fonts or Colors
windows, the document is the main window and the other window is the key window. The Find panel requires
Window Layering and Types of Windows
Key and Main Windows
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
20the user to supply information by typing it. Since the panel is the destination of the user's keystrokes, it's
marked as the key window. But the panel is just an instrument through which users can do work in another
window—the main window. In a document-based application, the main window isthe window for the current
Whenever a standard window becomesthe key window, it also becomesthe main window. When key-window
status shifts from a standard window to a panel, main-window status remains with the standard window.
So that users can pick out the main window when it's not the key window, the Application Kit highlights its
title bar and colorsthe window buttons. If the main window is also the key window, it has only the highlighting
of the key window. A menu command might affect either the key window or the main window, depending
on the command. For example, the Paste command can be used to enter text in a Find panel. But the Save
command saves the document displayed in the main window, and the Bold command turns the current
selection in the main window bold. For this reason, user actions in a panel or menu are associated with both
the key window and the main window:
● An action is first associated with the key window.
If the key window is a panel and it can't handle the action, the action is next associated with the main
Note that this order of precedence is reflected in the way windows are highlighted: The key window is always
marked, but the main window is marked only when it's not the key window. The main window is always in the
same application as the key window, the active application.
Changing a Window's Status
Windows that are already onscreen automatically change their status as the key or main window based on the
user's actions with the mouse and on how clicked views handle those mouse events. You can also set the key
and main windows programmatically by sending the relevant windows a makeKeyWindow or makeMainWindow
message. Setting the key and main windows programmatically is particularly useful when creating a new
window. Because making a window key is often combined with ordering the window to the front of the screen,
the NSWindow class defines a convenience method, makeKeyAndOrderFront:, that performs both operations.
Not all windows are suitable as key or main windows. For example, a window that merely displays information
and contains no objectsthat need to respond to events or action messages can completely forgo ever becoming
the key window. Similarly, a window that acts as a floating palette of itemsthat are only dragged out by mouse
actions never needs to be the key window. Such a window can be defined as a subclass of NSWindow that
overridesthe methods canBecomeKeyWindow and canBecomeMainWindow to return NO instead of the default
of YES. Defining a window this way prevents it from ever becoming the key or main window. Although the
NSWindow class defines these methods, only subclasses of NSPanel typically refuse to accept key or main
window status.
Window Layering and Types of Windows
Key and Main Windows
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
21Windows can be placed on the screen in three dimensions. Besides horizontal and vertical placement, windows
are layered back-to-front within distinct levels. Each application and document window exists in its own layer,
so documents from different applications can be interleaved. Clicking a window to bring it to the front doesn't
disturb the layering order of any other window. A window's depth in the layers is determined by when the
window was last accessed. When a user clicks an inactive document or chooses it from the Window menu,
only that document and any open utility windows should be brought to the front.
Window Levels
Windows are ordered within several distinct levels. Window levels group windows ofsimilar type and purpose
so that the more "important" ones(such as alert panels) appear in front of those lesser importance. A window's
level serves as a high-order bit to determine its position with regard to other windows. Windows can be
reordered with respect to each other within a given level; a given window, however, cannot be layered above
other windows in a higher level.
There are a number of predefined window levels, specified by constants defined by the NSWindow class. The
levels you typically use are: NSNormalWindowLevel, which specifies the default level;
NSFloatingWindowLevel, which specifiesthe level for floating palettes; and NSScreenSaverWindowLevel,
which specifies the level for a screen saver window. You might also use NSStatusWindowLevel for a status
window, or NSModalPanelWindowLevel for a modal panel. If you need to implement your own popup menus
you use NSPopUpMenuWindowLevel. The remaining two levels, NSTornOffMenuWindowLevel and
NSMainMenuWindowLevel, are reserved for system use.
Setting Ordering and Level Programmatically
You can use the orderWindow:relativeTo: method to order a window within its level in front of or in back
of another window. You more typically use convenience methods to specify ordering, such as
makeKeyAndOrderFront: (which also affectsstatus), orderFront:, and orderBack:, as well as orderOut:,
which removes a window from the screen. You use the isVisible method to determine whether a window
is on or off the screen. You can also set a window to be removed from the screen automatically when its
application isn't active using setHidesOnDeactivate:.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Window Layers and LevelsTypically you should have no need to programmatically set the level of a window, since Cocoa automatically
determines the appropriate level for a window based on its characteristics. A utility panel, for example, is
automatically assigned to NSFloatingWindowLevel. You can nevertheless set a window's level using the
setLevel: method; for example, you can set the level of a standard window to NSFloatingWindowLevel
if you want a utility window that looks like a standard window (for example to act as an inspector). This has
two disadvantages, however: firstly, it may violate the human interface guidelines; secondly, if you assign a
window to a floating level, you must ensure that you also set it to hide on deactivation of your application or
reset its level when your application is hidden. Cocoa automatically takes care of the latter aspect for you if
you use default window configurations.
There is currently no level specified to allow you to place a window above a screen saver window. If you need
to do this (for example, to show an alert while a screen saver is running), you can set the window's level to be
greater than that of the screen saver, as shown in the following example.
[aWindow setLevel:NSScreenSaverWindowLevel + 1];
Other than this specific case, you are discouraged from setting windows in custom levels since this may lead
to unexpected behavior.
Window Layers and Levels
Setting Ordering and Level Programmatically
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
23The are a number of different options that can be set regarding the window collection behavior of a window.
They include a window's behavior when using Spaces, Exposé, and the "Cycle Through Windows" command.
These options can be set using the setCollectionBehavior: method of NSWindow, by passing in at most
one constant from each group, combined using bitwise or operators. The current options may be accessed via
the collectionBehavior method.
Spaces Collection Behavior
There are three options that can be set for a window's Spaces collection behavior. The default is
NSWindowCollectionBehaviorDefault, which allows the window to be associated with one space at a
time. The second option is NSWindowCollectionBehaviorCanJoinAllSpaces. This option causes the
window to appear on all spaces, like the menu bar. The third option is
NSWindowCollectionBehaviorMoveToActiveSpace. This causesthe window to switch to the active space
when it is made active. Only one of these options may be used at a time.
If a window is currently associated with the active space, isOnActiveSpace returns YES. Otherwise, it returns
NO. Additionally, you can get an array of the window numbers of windows on one or all spaces using the
method windowNumbersWithOptions: and specified your desired options. The possible options are specified
by NSWindowNumberListOptions.
Exposé Collection Behavior
There are also three options that can be set for a window's Exposé collection behavior. If a window has a
window level of NSNormalWindowLevel, the default behavior is NSWindowCollectionBehaviorManaged,
which causes the window to participate in both Spaces and Exposé.
NSWindowCollectionBehaviorTransient causes the window to float in Spaces and be hidden in Exposé.
This is the default behavior if the window level is not NSNormalWindowLevel. The final option is
NSWindowCollectionBehaviorStationary, which causes the window to be unaffected by Exposé; i.e. it
stays visible and does not move, like the desktop window. Only one of these options may be used at a time.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Setting Window Collection BehaviorWindow Cycling Behavior
There are two options: NSWindowCollectionBehaviorParticipatesInCycle and
NSWindowCollectionBehaviorIgnoresCycle. These options cause the window to participate in the
window cycle for the "Cycle Through Windows" menu option or not participate in it, respectively.
Setting Window Collection Behavior
Window Cycling Behavior
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
25This article describes how to control a window's size and position, including how to set a window's minimum
and maximum size, how to constrain a window to the screen, how to cascade windowsso their title barsremain
visible, how to zoom a window as though the user pressed the zoom button, and how to center a window on
the screen.
Setting a Window's Size and Location
The center method places a window in the most prominent location on the screen, one suitable for important
messages and alert dialogs.
You can resize or reposition a window using setFrame:display: or setFrame:display:animate:—the
former is equivalent to the latter with the animate flag NO. You might use these methodsin particular to expand
or contract a window to show or hide a subview (such as a control that may be exposed by clicking a disclosure
triangle). If the animate argument in setFrame:display:animate: is YES, the method performs a smooth
resize of the window, where the total time for the resize can be obtained by calling animationResizeTime:.
The user can resize windows by clicking and dragging on the bottom right corner of the window. While the
user is resizing the window, inLiveResize will return YES. Otherwise, it returns NO. The user can generally
reposition windows by dragging only the title bar. If you want usersto be able to drag your window by clicking
elsewhere, you should override mouseDownCanMoveWindow so that it returns YES in any views that you want
to be draggable window regions. The methods isMovable and setMovable: determine whether the user
can move the window by clicking in its title bar or background.
To keep the window's top-left hand corner fixed when resizing, you must typically also reposition the origin,
as illustrated in the following example.
- (IBAction)showAdditionalControls:sender
NSRect frame = [myWindow frame];
if (frame.size.width <= MIN_WIDTH_WITH_ADDITIONS)
frame.size.width = MIN_WIDTH_WITH_ADDITIONS;
frame.size.height += ADDITIONS_HEIGHT;
frame.origin.y -= ADDITIONS_HEIGHT;
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Sizing and Placing Windows[myWindow setFrame:frame display:YES animate:YES];
// implementation continues...
Note that the window's delegate does not receive windowWillResize:toSize: messages when the window
is resized in this way. It is your responsibility to ensure that the window's new size is acceptable.
The window's delegate doesreceive windowDidResize: messages. You can implement windowDidResize:
to add or remove subviews at suitable junctures. There are no additional flags to denote that the window is
performing an animated resize operation (as distinct from a user-initiated resize). It is therefore up to you to
capture relevant state information so that you can update the window contents appropriately in
Window Cascading
If you use the Cocoa document architecture, you can use the setShouldCascadeWindows: method of
NSWindowController to set whether the window, when it is displayed, should cascade in relation to other
document windows(that is, have a slightly offset location so that the title bars of previously displayed windows
are still visible). The default is true, so typically you have no additional work to perform.
If you are not using the document architecture, you can use the cascadeTopLeftFromPoint: method of
NSWindow to cascade windows yourself. The method returns a point shifted from the top-left corner of the
window that can be passed to a subsequent invocation of cascadeTopLeftFromPoint: to position the next
window so the title bars of both windows are fully visible.
Window Zooming
You use the zoom: method to toggle the size and location of a window between its standard state, as
determined by the application, and its user state: a new size and location the user may have set by moving or
resizing the window.
Constraining a Window's Size and Location
You can use setContentMinSize: and setContentMaxSize: to limit the user's ability to resize the
window—note that you can still set it to any size programmatically. Similarly, you can use
setContentAspectRatio: to keep a window's width and height at the same proportions as the user resizes
it, and setContentResizeIncrements: to make the window resize in discrete amountslarger than a single
pixel. (Aspect ratio and resize increments are mutually exclusive attributes.) In general, you should use the
Sizing and Placing Windows
Constraining a Window's Size and Location
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
27setContent... methodsinstead of those that affect the window'sframe (setAspectRatio:, setMaxSize:,
and so on). These are preferred because they avoid confusion for windows with toolbars, and also are typically
a better model since you control the content of the window but not the frame.
You can use the constrainFrameRect:toScreen: method to adjust a proposed frame rectangle so that
it lies on the screen in such a way that the user can move and resize a window. However, you should make
sure your window fits onscreen before display. Note that any NSWindow with a title bar automatically constrains
itself to the screen. The cascadeTopLeftFromPoint: method shifts the top left point by an amount that
allows one window to be placed relative to another so that both their title bars are visible.
Additionally, when a window is about to be resized, the window's delegate will be sent a
windowWillResize:toSize: message. You can implement that method in your delegate to easily control
your window's size.
Sizing and Placing Windows
Constraining a Window's Size and Location
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
28A window can store its placement in the user defaults system, so that it appears in the same location the next
time the user starts the application. The saveFrameUsingName: method stores the frame rectangle, and
setFrameUsingName: setsit from the value in user defaults. You can also use the setFrameAutosaveName:
method to have a window save the frame rectangle any time it changes. However, for the correct frame to be
saved, you must ensure that the window controller for the window in question doesn't cascade the windows
under its charge. You accomplish this task by sending setShouldCascadeWindows:NO to the controller, as
shown in Listing 1.
Listing 1 Saving a window's frame automatically
NSWindow *window = // the window in question
[[window windowController] setShouldCascadeWindows:NO]; // Tell the controller
to not cascade its windows.
[window setFrameAutosaveName:[window representedFilename]]; // Specify the autosave
name for the window.
To expunge a frame rectangle from the defaults system, use the class method removeFrameUsingName:.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Saving a Window's Position into the User's DefaultsWhen a user minimizes a window, it's removed from the screen and replaced with a smaller counterpart in the
The miniaturize: and deminiaturize: methods reduce and reconstitute a window, and
performMiniaturize: simulatesthe user clicking the window's minimize button. You can also set the image
and title displayed in a freestanding mini-window by sending setMiniwindowImage: and
setMiniwindowTitle: messages to the NSWindow object.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Minimizing WindowsMost Cocoa applications include the Window menu, which displays the titles of various of the application's
windows. When you change a window's title, this change is automatically reflected in the Window menu. This
menu automatically lists windowsthat have a title bar and are resizable and that can become the main window
(as described in "Window Layering and Types of Windows" (page 18)). Typically you can rely on the automatic
updating provided by Cocoa. In rare circumstances, however, you might want to modify the default behavior.
You can exclude a window that would otherwise be listed in the Window menu by sending it a
setExcludedFromWindowsMenu:YES message. Since they cannot become main, NSPanel objects are
excluded from the Windows menu. Instances of subclasses of NSPanel can be included in the menu by
returning NO from its isExcludedFromWindowsMenu method and YES from its canBecomeMainWindow
method. If you change a window's configuration such that it should be added to or removed from the Window
menu, you can update the Window menu by sending the shared application instance
addWindowsItem:title:filename: or removeWindowsItem:.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Using the Window MenuYou usually configure most aspects of a window's appearance in Interface Builder. Sometimes, however, you
may need to create a window programmatically, or alter its appearance after it has been created.
Setting a Window's Style
The peripheral elements that a window displays define its style. Though you can't access and manipulate them
directly, you can determine at initialization whether a window has them by providing a style mask to the
initializer. There are four possible style elements,specifiable by combining their mask values using the C bitwise
OR operator:
Element Mask Value
A title bar NSTitledWindowMask
A close button NSClosableWindowMask
A minimize button NSMiniaturizableWindowMask
A resize bar, border, or box NSResizableWindowMask
You can also specify NSBorderlessWindowMask, in which case none of these style elements is used.
Typically, you set a window's appearance once, when it is first created. Sometimes, however, you want to
enable or disable a button in the title bar to reflect changed context. To do this, you first retrieve the button
from the window using the standardWindowButton: of NSWindow method and then set its enabled state,
as in the following example.
NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton];
[closeButton setEnabled:NO];
The constants required to access standard title bar widgets are defined in the API reference for NSWindow.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Setting a Window's AppearanceSetting a Window's Color and Transparency
You can set a window's background color and transparency using the methods setBackgroundColor: and
setAlphaValue:, respectively.
You can set a window's background color to a non-opaque color. This does not affect the window's title bar;
it only makes the background itself transparent if the window is not opaque, as illustrated in the following
[myWindow setOpaque:NO]; // YES by default
NSColor *semiTransparentBlue =
[NSColor colorWithDeviceRed:0.0 green:0.0 blue:1.0 alpha:0.5];
[myWindow setBackgroundColor:semiTransparentBlue];
Views placed on a non-opaque window with a transparent background color retain their own opacity. If you
want to make the entire window (including the title bar and views placed on the window) transparent, you
should use setAlphaValue:.
Setting a Window's Color Space
You can set a window's colorspace using setColorSpace: and can retrieve the window's current colorspace
using colorSpace. NSColorSpace objects for use with setColorSpace: may be obtained using the class
methods documented in NSColorSpace Class Reference .
Setting a Window's Content Border Thickness
Beginning in OS X version 10.5, windows automatically have a textured gradient applied to their backgrounds.
The area on which the gradient is drawn is determined automatically. At times, however, this may not work
correctly. If your window does not look correct with automatic gradient calculation, disable it by calling
setAutorecalculatesContentBorderThickness:forEdge: with a value of NO and the edge to disable
automatic calculation for. The value of this property may be accessed using the method
You can also set and access the content border thickness manually using
setContentBorderThickness:forEdge: and contentBorderThicknessForEdge:, respectively.
Setting a Window's Appearance
Setting a Window's Color and Transparency
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
33A titled window can display an arbitrary title or one derived from a filename. The setTitle: method puts an
arbitrary string on the title bar. The setTitleWithRepresentedFilename: method formats a filename in
the title bar in a readable format and associates the window with that file. You can set the associated file
without changing the title using setRepresentedFilename:. You can use the association between the
window and the file in any way you see fit. One convenience offered by the NSWindow class is marking the
file as having been changed, so that the user is prompted to save it on closing the window. The method for
marking the document as having been changed is setDocumentEdited:. When the window closes, its
delegate can check if the files has been changed using isDocumentEdited to see whether the document
needs to be saved.
Additionally, starting in OS X version 10.5, you can set a window's represented document by URL using the
setRepresentedURL: method. You can get the URL of the document currently represented by a window
using the representedURL method. The window will automatically use the known icon for the file type of
the specified file, if one exists. To customize the document icon, you can use the following code segment:
[[NSWindow standardWindowButton:NSWindowDocumentIconButton] setImage:customImage].
By default, a Command-click or Control-click on the rectangle containing a window's document icon button
and title will show a path popup. To customize this behavior, you can implement
window:shouldPopUpDocumentPathMenu: in your window's delegate. You can return NO from this method
to stop the window from showing the path popup.
You can also customize the document icon's default drag behavior by implementing the
window:shouldDragDocumentWithEvent:from:withPasteboard: in the window's delegate. You can
return NO to prohibit dragging the document icon.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Setting a Window's Title and Represented FileNearly every window has a corresponding display window device in the window server. The window device
holdsthe window's drawn image, and hastwo attributes determined by the window server and many attributes
that the window controls. The window server assigns the window device a unique identifier (within an
application). This is the window number, and it can be accessed using the windowNumber method. Each
window also has a graphics state that most of its views share for drawing (views can create their own as well).
The gState method returns its identifier. The attributes under direct window control are the following:
● Backing store type, described in "Specifying How To Store the Window's Image" (page 35)
● Backing location, described in "Specifying Where To Store the Window's Image" (page 36)
● Window device creation, described in "Specifying When the Window's Image Is Created" (page 36)
● One shot, described in "Specifying Whether the Window's Image Persists When Offscreen" (page 37)
● Depth limit, described in "Specifying the Depth Limit for the Window's Image" (page 37)
● Dynamic depth limit, described in "Specifying Whether the Depth Limit Changes to the Screen's
Capacity" (page 37)
● Content sharing, described in "Specifying Whether Window Content Can Be Read or Written by Another
Process" (page 37).
Specifying How To Store the Window's Image
A window device's backing store type determines how the window'simage isstored. It'sset when the window
is initialized and can be one of three types.
A buffered window device renders all drawing into a display buffer and then flushes it to the screen. Always
drawing to the buffer produces very smooth display, but can require significant amounts of memory. Buffered
windows are best for displaying material that must be redrawn often, such as text. You must also use buffered
windows if you want your windows to support transparency.
A retained window device also uses a buffer, but draws directly to the screen where possible and to the buffer
for any portions that are obscured.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Setting Attributes for the Window's ImageA nonretained window device has no buffer at all, and must redraw portions as they're exposed. Further, this
redrawing is suspended when the window's display mechanism is preempted. For example, if the user drags
a window across a nonretained window, the nonretained window is "erased" and isn't redrawn until the user
releases the mouse.
Both retained and nonretained windows are also subject to a flashing effect as individual drawing operations
are performed, but their results do get to the screen more quickly than those of buffered windows.
You can change the backing store type between buffered and retained after initialization using the
setBackingType: method.
Specifying Where To Store the Window's Image
The window server chooses whether to place the backing store for a buffered window in main memory or
video memory. It will choose the location that providesthe best overall performance. You can query the window
server to determine where your window's backing store is located using the preferredBackingLocation
You may choose to set a preferred location for a Window's backing store using the
setPreferredBackingLocation: method. While the window server is not required to respect this preferred
backing location, it will attempt to do so. You should not change the preferred backing location without testing
how it affects the performance of your application.
Specifying When the Window's Image Is Created
The defer argument to the initializer specifies whether the window creates its window device immediately
or only when it's moved on screen. Deferring creation of the window device can offer some performance gain
for windows that aren't displayed immediately because it reduces the amount of work that needs to be
performed up front. Deferring creation of the window device is particularly useful when creation of the window
itself can't be deferred or when an window is needed for purposes other than displaying content. Submenus
with key equivalents, for example, must exist for the key equivalents to work, but may never actually be
Setting Attributes for the Window's Image
Specifying Where To Store the Window's Image
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
36Specifying Whether the Window's Image Persists When Offscreen
Memory can also be saved by destroying the window device when the window is removed from the screen.
The setOneShot: method controls this behavior. One-shot window devices exist only when their windows
are onscreen.
Specifying the Depth Limit for the Window's Image
Like the display hardware, a window device's buffer has a depth, or a limit to the memory allotted each pixel.
Buffered and retained windows start out with the same depth as the main display or 16 bits, whichever is
deeper. These settings stay in effect unless changed using the setDepthLimit: method, which takes as an
argument a window depth limit created using the NSBestDepth function.
SpecifyingWhether the Depth Limit Changesto the Screen's Capacity
Keeping a window's depth at its richest preserves the displayed image, but may incur unnecessary memory
overhead when the window buffer depth is deeper than the screen depth. You can use the
setDynamicDepthLimit: method to tell a window to match the depth of the screen it's on. When it's moved
to a new screen, a window with a dynamic depth limit adjusts its buffer to the new depth before redrawing.
Making a window's depth limit dynamic overrides the limit set using setDepthLimit:, and removing the
dynamic limit reverts the window to the default limit.
Specifying Whether Window Content Can Be Read or Written by
Another Process
The contents of your window can be made available to other processes. By default, the contents of your window
can be read but not written to by other processes. This allows system services to work with your window's
contents and also allows other applications to capture a snapshot of your windows contents.
You can override the default behavior using the setSharingType: method. Changing the sharing type to
NSWindowSharingNone prevents other systems from capturing your window's image data. If you do this,
however, your window will not be able to participate in a number of system services; therefore, this setting
should be used with caution. If you set your window's sharing type to NSWindowSharingReadWrite, other
processes can both read and modify the window's content.
Setting Attributes for the Window's Image
Specifying Whether the Window's Image Persists When Offscreen
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
37As described in NSResponder Class Reference , most events coming into an application make their way to a
window in a sendEvent: message. A key event is directed at the key window, while a mouse event is directed
at whatever window lies under the pointer. If an event affects the window directly—resizing or moving it, for
example—it performs the appropriate operation itself and sends messages to its delegate informing it of its
intentions, thus allowing your application to intercede. The window sends other events up its responder chain
from the appropriate starting point: the first responder for a key event, the view under the pointer for a mouse
event. These events are then typically handled by some view object in the window. See Cocoa Event Handling
Guide for more information on how to intercept and handle events.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Handling Events in WindowsA window's first responder is often a view object selected by the user clicking it. For text fields and other view
objects (mainly subclasses of NSControl), the user can select the first responder with the keyboard using the
Tab and Shift keys. The NSView class defines the methods for setting up and examining the loop of objects
that the user can select in this manner. A view that's the first responder is called the key view, and the views
that can become the key view in a window are linked together in the window's key view loop. You normally
set up the key view loop using Interface Builder, establishing connections between the nextKeyView outlets
of views in the window and setting the window's initialFirstResponder outlet to the view that you want
selected when the window is first placed onscreen. If you do not set this outlet, the window sets a key loop
(not necessarily the same as the one you would have specified!) and picks a default initial first responder for
In addition to the key view loop, a window can have a default button cell, which uses the Return (or Enter)
key as its key equivalent. The setDefaultButtonCell: method establishes this button cell; you can also
set it in Interface Builder by setting a button cell's key equivalent to '\r'. The default button cell draws itself
as a focal element for keyboard interface control unless another button cell is focused on. In this case, it
temporarily draws itself as normal and disables its key equivalent. Another default key established by the
NSWindow class is the Escape key, which immediately aborts a modal loop (described in "How Modal Windows
Work" (page 12)).
See NSResponder Class Reference for more information on keyboard interface control.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Using Keyboard Interface Control in WindowsEach window has a text object that is shared for light editing tasks. This object, the window's field editor, is
inserted in the view hierarchy when an object needsto editsome text and removed when the object isfinished.
The field editor is used by NSTextField objects and other controls, for example, to edit the text that they
display. The fieldEditor:forObject: method returns a window's field editor, after asking the delegate
for a substitute using windowWillReturnFieldEditor:toObject:. You can override the
fieldEditor:forObject: method of NSWindow in subclasses or provide a delegate to substitute a class
of text object different from the NSTextView default, thereby customizing text editing in your application.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Using the Window's Field EditorThe NSWindow class offers observers a rich set of notifications, which it broadcasts on such occurrences as
gaining or losing key or main window status, minimizing, moving or resizing, becoming exposed, and closing.
Each notification is matched to a delegate method, so a window's delegate is automatically registered for all
notifications that it has methods for. The NSWindow class also offers its delegate a few other methods, such
as windowShouldClose:, which requests approval to close, windowWillResize:toSize:, which allows
the delegate to constrain the window'ssize, windowWillUseStandardFrame:defaultFrame:, which allows
the delegate to set the window frame for zooming, and windowWillReturnFieldEditor:toObject:,
which gives the delegate a chance to modify the field editor or substitute a different editor. See the individual
notification and delegate method descriptions for more information.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Using Window Notifications and Delegate MethodsThe NSWindow class defines some methods for image dragging, in case the user wants to drag an object into
or out of a window. Although most dragging operations are initiated by and occur between view objects, the
NSWindow class also defines an image-dragging method,
dragImage:at:offset:event:pasteboard:source:slideBack:. A window can also serve as the
destination for dragging operations, registering the types it accepts with registerForDraggedTypes: and
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Dragging Images to and from WindowsYou can change the cursor image when the cursor is within a specified area of a view in a window. To do this,
use the NSTrackingArea class, along with the cursorUpdate: method of the NSResponder class. For
specifics, read "Using Tracking-Area Objects" in Cocoa Event Handling Guide .
For details on the NSTrackingArea class itself, refer to NSTrackingArea Class Reference .
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Updating the Cursor Image in a WindowTo support transitory drawing by views, the NSWindow class defines methods that temporarily cache a portion
of its raster image so that it can be restored later. This feature is useful for situations where highly dynamic
drawing must be done over the otherwise static image of the window. For example, in a drawing program
where the user drags lines and other shapes directly onto a canvas, it's more efficient to restore the window's
cached image and draw anew over that than to have all the views send display instructions to the window
server. For more information,see the method descriptionsfor cacheImageInRect:, restoreCachedImage,
and discardCachedImage.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Caching Window ImagesThis table describes the changes to Window Programming Guide .
Date Notes
Revised the article "Updating the Cursor Image in a Window" (page 43),
previously titled "Setting Pointer Rectangles for Windows."
2009-05-15 Updated for OS X v10.6.
Added information on the use of backing locations to improve
2008-10-15 Provided links to delegate methods.
Clarified the behavior of the setFrameAutosaveName: method in
conjunction with a window's window controller.
Added window-controller requirement for the NSWindow
setFrameAutosaveName: method to "Saving a Window's Position into
the User's Defaults" (page 29).
Made correction to "Using the Windows Menu" article. Changed title from
"Windows and Panels."
Updated "Setting a Window's Appearance" (page 32) to cover enabling
and disabling buttons in the title bar, and to discuss setting a window's
background color and transparency.
"Setting a Window's Level" renamed "Window Layers and Levels" (page
22) and augmented.
"Changing the Key and Main Windows" renamed to "Window Layering
and Types of Windows" (page 18) and augmented.
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
Document Revision HistoryDate Notes
Augmented "Sizing and Placing Windows" (page 26) to discuss animated
resizing, window cascading, and constraining window size and position.
Minor changes to "Using the Window Menu" (page 31).
Clarified the concepts of key and main windowsin "Window Layering and
Types of Windows" (page 18)".
2002-11-12 Revision history was added to existing topic.
Document Revision History
2009-11-27 | © 2002, 2009 Apple Inc. All Rights Reserved.
46Apple Inc.
© 2002, 2009 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrievalsystem, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer for personal use only and to print
copies of documentation for personal use
provided that the documentation contains
Apple's copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-labeled computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
Apple, the Apple logo, Cocoa, Exposé, Mac,
Numbers, OS X, and Spaces are trademarks of
Apple Inc., registered in the U.S. and other
Even though Apple has reviewed this document,
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer,
agent, or employee is authorized to make any
modification, extension, or addition to this warranty.
Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
you specific legal rights, and you may also have other
rights which vary from state to state.
AV Foundation
Programming GuideContents
About the AV Foundation Framework 4
At a Glance 5
Representing and Using Media with AV Foundation 5
Concurrent Programming with AV Foundation 7
Prerequisites 8
Using Assets 9
Creating an Asset Object 9
Options for Initializing an Asset 9
Accessing the User's Assets 10
Preparing an Asset for Use 11
Getting Still Images From a Video 12
Generating a Single Image 13
Generating a Sequence of Images 14
Trimming and Transcoding a Movie 15
Reading and Writing Assets 17
Playback 18
Playing Assets 18
Handling Different Types of Asset 20
Playing an Item 21
Changing the Playback Rate 21
Seeking—Repositioning the Playhead 22
Playing Multiple Items 23
Monitoring Playback 23
Responding to a Change in Status 24
Tracking Readiness for Visual Display 25
Tracking Time 25
Reaching the End of an Item 26
Putting it all Together: Playing a Video File Using AVPlayerLayer 26
The Player View 27
A Simple View Controller 27
Creating the Asset 28
Responding to the Player Item's Status Change 30
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
2Playing the Item 31
Media Capture 32
Use a Capture Session to Coordinate Data Flow 33
Configuring a Session 34
Monitoring Capture Session State 35
An AVCaptureDevice Object Represents an Input Device 35
Device Characteristics 36
Device Capture Settings 36
Configuring a Device 40
Switching Between Devices 41
Use Capture Inputs to Add a Capture Device to a Session 41
Use Capture Outputs to Get Output from a Session 42
Saving to a Movie File 43
Processing Frames of Video 46
Capturing Still Images 47
Showing the User What's Being Recorded 49
Video Preview 49
Showing Audio Levels 50
Putting it all Together: Capturing Video Frames as UIImage Objects 50
Create and Configure a Capture Session 51
Create and Configure the Device and Device Input 51
Create and Configure the Data Output 52
Implement the Sample Buffer Delegate Method 52
Starting and Stopping Recording 53
Time and Media Representations 54
Representation of Assets 54
Representations of Time 55
CMTime Represents a Length of Time 55
CMTimeRange Represents a Time Range 57
Representations of Media 58
Converting a CMSampleBuffer to a UIImage 59
Document Revision History 62
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
ContentsAV Foundation is one of several frameworks that you can use to play and create time-based audiovisual media.
It provides an Objective-C interface you use to work on a detailed level with time-based audiovisual data. For
example, you can use it to examine, create, edit, or reencode media files. You can also get input streams from
devices and manipulate video during realtime capture and playback.
Core Audio
Media Player
AV Foundation
iOS 3 Audio
Core Media Core Animation
You should typically use the highest-level abstraction available that allows you to perform the tasks you want.
For example, in iOS:
If you simply want to play movies, you can use the Media Player Framework (MPMoviePlayerController
or MPMoviePlayerViewController), or for web-based media you could use a UIWebView object.
● To record video when you need only minimal control over format, use the UIKit framework
Note, however, thatsome of the primitive data structuresthat you use in AV Foundation—including time-related
data structures and opaque objectsto carry and describemedia data—are declared in the Core Media framework.
AV Foundation is available in iOS 4 and later, and OS X 10.7 and later. This document describes AV Foundation
as introduced in iOS 4.0. To learn about changes and additions to the framework in subsequent versions, you
should also read the appropriate release notes:
● AV Foundation Release Notes describe changes made for iOS 5.
● AV Foundation Release Notes (iOS 4.3) describe changes made for iOS 4.3 and included in OS X 10.7.
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
About the AV Foundation FrameworkRelevant Chapters: "Time and Media Representations" (page 54)
At a Glance
There are two facets to the AV Foundation framework—API related just to audio, which was available prior to
iOS 4; and API introduced in iOS 4 and later. The older audio-related classes provide easy ways to deal with
audio. They are described in Multimedia Programming Guide , not in this document.
● To play sound files, you can use AVAudioPlayer.
● To record audio, you can use AVAudioRecorder.
You can also configure the audio behavior of your application using AVAudioSession; this is described in
Audio Session Programming Guide .
Representing and Using Media with AV Foundation
The primary class that the AV Foundation framework uses to represent media is AVAsset. The design of the
framework is largely guided by this representation. Understanding its structure will help you to understand
how the framework works. An AVAsset instance is an aggregated representation of a collection of one or
more pieces of media data (audio and video tracks). It provides information about the collection as a whole,
such as its title, duration, natural presentation size, and so on. AVAsset is not tied to particular data format.
AVAsset is the superclass of other classes used to create asset instances from media at a URL (see "Using
Assets" (page 9)) and to create new compositions (see "Editing" (page 7)).
Each of the individual pieces of media data in the asset is of a uniform type and called a track. In a typical
simple case, one track represents the audio component, and another represents the video component; in a
complex composition, however, there may be multiple overlapping tracks of audio and video. Assets may also
have metadata.
A vital concept in AV Foundation is that initializing an asset or a track does not necessarily mean that it is ready
for use. It may require some time to calculate even the duration of an item (an MP3 file, for example, may not
contain summary information). Rather than blocking the current thread while a value is being calculated, you
ask for values and get an answer back asynchronously through a callback that you define using a block.
About the AV Foundation Framework
At a Glance
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
5Relevant Chapters: "Using Assets" (page 9)
"Time and Media Representations" (page 54)
AVFoundation allows you to manage the playback of asset in sophisticated ways. To support this, it separates
the presentation state of an asset from the asset itself. This allows you to, for example, play two different
segments of the same asset at the same time rendered at different resolutions. The presentation state for an
asset is managed by a player item object; the presentation state for each tracks within an asset is managed
by a player item track objects. Using the player item and player item tracks you can, for example, set the size
at which the visual portion of the item is presented by the player, set the audio mix parameters and video
composition settings to be applied during playback, or disable components of the asset during playback.
You play player items using a player object, and direct the output of a player to Core Animation layer. On
iOS 4.1 and later, you can use a player queue to schedule playback of a collection of player items in sequence.
Relevant Chapters: "Playback" (page 18)
Reading, Writing, and Reencoding Assets
AV Foundation allows you to create new representations of an asset in several ways. You can simply reencode
an existing asset, or—on iOS 4.1 and later—you can perform operations on the contents of an asset and save
the result as a new asset.
You use an export session to reencode an existing asset into a format defined by one of a small number of
commonly-used presets. If you need more control over the transformation, on iOS 4.1 and later you can use
an asset reader and asset writer object in tandem to convert an asset from one representation to another.
Using these objects you can, for example, choose which of the tracks you want to be represented in the output
file, specify your own output format, or modify the asset during the conversion process.
To produce a visual representation of the waveform, you use an asset reader to read the audio track of an
About the AV Foundation Framework
At a Glance
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
6Relevant Chapters: "Using Assets" (page 9)
To create thumbnail images of video presentations, you initialize an instance of AVAssetImageGenerator
using the asset from which you want to generate thumbnails. AVAssetImageGenerator uses the default
enabled video track(s) to generate images.
Relevant Chapters: "Using Assets" (page 9)
AV Foundation uses compositions to create new assets from existing pieces of media (typically, one or more
video and audio tracks). You use a mutable composition to add and remove tracks, and adjust their temporal
orderings. You can also set the relative volumes and ramping of audio tracks; and set the opacity, and opacity
ramps, of video tracks. A composition is an assemblage of pieces of media held in memory. When you export
a composition using an export session, it's collapsed to a file.
On iOS 4.1 and later, you can also create an asset from media such as sample buffers or still images using an
asset writer.
Media Capture and Access to Camera
Recording input from cameras and microphonesis managed by a capture session. A capture session coordinates
the flow of data from input devices to outputs such as a movie file. You can configure multiple inputs and
outputs for a single session, even when the session is running. You send messages to the session to start and
stop data flow.
In addition, you can use an instance of preview layer to show the user what a camera is recording.
Relevant Chapters: "Media Capture" (page 32)
Concurrent Programming with AV Foundation
Callouts from AV Foundation—invocations of blocks, key-value observers, or notification handlers—are not
guaranteed to be made on any particular thread or queue. Instead, AV Foundation invokes these handlers on
threads or queues on which it performs its internal tasks. You are responsible for testing whether the thread
or queue on which a handler isinvoked is appropriate for the tasks you want to perform. If it's not (for example,
if you want to update the user interface and the callout is not on the main thread), you must redirect the
execution of your tasks to a safe thread or queue that you recognize, or that you create for the purpose.
About the AV Foundation Framework
At a Glance
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
7If you're writing amultithreaded application, you can use the NSThreadmethod isMainThread or [[NSThread
currentThread] isEqual:<#A stored thread reference#>] to test whether the invocation thread
is a thread you expect to perform your work on. You can redirect messages to appropriate threads using
methods such as performSelectorOnMainThread:withObject:waitUntilDone: and
performSelector:onThread:withObject:waitUntilDone:modes:. You could also use
dispatch_async(3) OS X Developer Tools Manual Page to "bounce"to your blocks on an appropriate
queue, either the main queue for UI tasks or a queue you have up for concurrent operations. For more about
concurrent operations, see Concurrency Programming Guide ; for more about blocks, see Blocks Programming
AV Foundation is an advanced Cocoa framework. To use it effectively, you must have:
● A solid understanding of fundamental Cocoa development tools and techniques
● A basic grasp of blocks
● A basic understanding of key-value coding and key-value observing
● For playback, a basic understanding of Core Animation (see Core Animation Programming Guide )
About the AV Foundation Framework
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
8Asset can come from a file or from media in the user's iPod Library or Photo library. Simply creating an asset
object, though, does not necessarily mean that all the information that you might want to retrieve for that
item is immediately available. Once you have a movie asset, you can extract still images from it, transcode it
to another format, or trim the contents.
Creating an Asset Object
To create an asset to represent any resource that you can identify using a URL, you use AVURLAsset. The
simplest case is creating an asset from a file:
NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
Options for Initializing an Asset
AVURLAsset's initialization methods take as their second argument an options dictionary. The only key used
in the dictionary is AVURLAssetPreferPreciseDurationAndTimingKey. The corresponding value is a
boolean (contained in an NSValue object) that indicates whether the asset should be prepared to indicate a
precise duration and provide precise random access by time.
Getting the exact duration of an asset may require significant processing overhead. Using an approximate
duration is typically a cheaper operation and sufficient for playback. Thus:
If you only intend to play the asset, either pass nil instead of a dictionary, or pass a dictionary that contains
the AVURLAssetPreferPreciseDurationAndTimingKey key and a corresponding value of NO
(contained in an NSValue object).
If you want to add the asset to a composition (AVMutableComposition), you typically need precise
randomaccess. Pass a dictionary that containsthe AVURLAssetPreferPreciseDurationAndTimingKey
key and a corresponding value of YES (contained in an NSValue object—recall that NSNumber inherits
from NSValue):
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
Using AssetsNSURL *url = <#A URL that identifies an audiovisual asset such as a movie
NSDictionary *options = @{ AVURLAssetPreferPreciseDurationAndTimingKey :
AVURLAsset *anAssetToUseInAComposition = [[AVURLAsset alloc]
initWithURL:url options:options];
Accessing the User's Assets
To access the assets managed the iPod Library or by the Photos application, you need to get a URL of the asset
you want.
● To access the iPod Library, you create an MPMediaQuery instance to find the item you want, then get its
URL using MPMediaItemPropertyAssetURL.
For more about the Media Library, see Multimedia Programming Guide .
● To access the assets managed by the Photos application, you use ALAssetsLibrary.
The following example shows how you can get an asset to represent the first video in the Saved Photos Album.
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup
*group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just videos.
[group setAssetsFilter:[ALAssetsFilter allVideos]];
// For this example, we're only interested in the first item.
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0]
usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL
*innerStop) {
// The end of the enumeration is signaled by asset ==
if (alAsset) {
Using Assets
Creating an Asset Object
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
10ALAssetRepresentation *representation = [alAsset
NSURL *url = [representation url];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url
// Do something interesting with the AV asset.
failureBlock: ^(NSError *error) {
// Typically you should handle an error more gracefully than
NSLog(@"No groups");
Preparing an Asset for Use
Initializing an asset (or track) does not necessarily mean that all the information that you might want to retrieve
for that item is immediately available. It may require some time to calculate even the duration of an item (an
MP3 file, for example, may not contain summary information). Rather than blocking the current thread while
a value is being calculated, you should use the AVAsynchronousKeyValueLoading protocol to ask for values
and get an answer back later through a completion handler you define using a block. (AVAsset and
AVAssetTrack conform to the AVAsynchronousKeyValueLoading protocol.)
You test whether a value is loaded for a property using statusOfValueForKey:error:. When an asset is
first loaded, the value of most or all of its properties is AVKeyValueStatusUnknown. To load a value for one
or more properties, you invoke loadValuesAsynchronouslyForKeys:completionHandler:. In the
completion handler, you take whatever action is appropriate depending on the property's status. You should
always be prepared for loading to not complete successfully, either because it failed for some reason such as
a network-based URL being inaccessible, or because the load was canceled. .
NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = @[@"duration"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
Using Assets
Preparing an Asset for Use
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
11NSError *error = nil;
AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"duration"
switch (tracksStatus) {
case AVKeyValueStatusLoaded:
[self updateUserInterfaceForDuration];
case AVKeyValueStatusFailed:
[self reportError:error forAsset:asset];
case AVKeyValueStatusCancelled:
// Do whatever is appropriate for cancelation.
If you want to prepare an asset for playback, you should load its tracks property. For more about playing
assets, see "Playback" (page 18).
Getting Still Images From a Video
To get still images such as thumbnails from an asset for playback, you use an AVAssetImageGenerator
object. You initialize an image generator with your asset. Initialization may succeed, though, even if the asset
possesses no visual tracks at the time of initialization, so if necessary you should test whether the asset has
any tracks with the visual characteristic using tracksWithMediaCharacteristic:.
AVAsset anAsset = <#Get an asset#>;
if ([anAsset tracksWithMediaCharacteristic:AVMediaTypeVideo]) {
AVAssetImageGenerator *imageGenerator =
[AVAssetImageGenerator assetImageGeneratorWithAsset:anAsset];
// Implementation continues...
Using Assets
Getting Still Images From a Video
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
12You can configure several aspects of the image generator, for example, you can specify the maximum dimensions
for the images it generates and the aperture mode using maximumSize and apertureMode respectively.You
can then generate a single image at a given time, or a series of images. You must ensure that you keep a strong
reference to the image generator until it has generated all the images.
Generating a Single Image
You use copyCGImageAtTime:actualTime:error: to generate a single image at a specific time. AV
Foundation may not be able to produce an image at exactly the time you request, so you can pass as the
second argument a pointer to a CMTime that upon return contains the time at which the image was actually
AVAsset *myAsset = <#An asset#>];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
NSError *error;
CMTime actualTime;
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint
actualTime:&actualTime error:&error];
if (halfWayImage != NULL) {
NSString *actualTimeString = (NSString *)CMTimeCopyDescription(NULL, actualTime);
NSString *requestedTimeString = (NSString *)CMTimeCopyDescription(NULL,
NSLog(@"Got halfWayImage: Asked for %@, got %@", requestedTimeString,
// Do something interesting with the image.
Using Assets
Getting Still Images From a Video
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
13Generating a Sequence of Images
To generate a series of images, you send the image generator a
generateCGImagesAsynchronouslyForTimes:completionHandler:message. The first argument is an
array of NSValue objects, each containing a CMTime, specifying the asset times for which you want images
to be generated. The second argument is a block that serves as a callback invoked for each image that is
generated. The block arguments provide a result constant that tells you whether the image was created
successfully or if the operation was canceled, and, as appropriate:
● The image.
● The time for which you requested the image and the actual time for which the image was generated.
● An error object that describes the reason generation failed.
In your implementation of the block, you should check the result constant to determine whether the image
was created. In addition, you must ensure that you keep a strong reference to the image generator until it has
finished creating the images.
AVAsset *myAsset = <#An asset#>];
// Assume: @property (strong) AVAssetImageGenerator *imageGenerator;
self.imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:myAsset];
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 600);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 600);
CMTime end = CMTimeMakeWithSeconds(durationSeconds, 600);
NSArray *times = @[NSValue valueWithCMTime:kCMTimeZero],
[NSValue valueWithCMTime:firstThird], [NSValue
[NSValue valueWithCMTime:end]];
[imageGenerator generateCGImagesAsynchronouslyForTimes:times
completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime
AVAssetImageGeneratorResult result, NSError
*error) {
NSString *requestedTimeString = (NSString *)
CFBridgingRelease(CMTimeCopyDescription(NULL, requestedTime));
Using Assets
Getting Still Images From a Video
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
14NSString *actualTimeString = (NSString *)
CFBridgingRelease(CMTimeCopyDescription(NULL, actualTime));
NSLog(@"Requested: %@; actual %@", requestedTimeString,
if (result == AVAssetImageGeneratorSucceeded) {
// Do something interesting with the image.
if (result == AVAssetImageGeneratorFailed) {
NSLog(@"Failed with error: %@", [error localizedDescription]);
if (result == AVAssetImageGeneratorCancelled) {
You can cancel the generation of the image sequence by sending the image generator a
cancelAllCGImageGeneration message.
Trimming and Transcoding a Movie
You can transcode a movie from one format to another, and trim a movie, using an AVAssetExportSession
object. An export session is a controller object that manages asynchronous export of an asset. You initialize
the session using the asset you want to export and the name of a export preset that indicates the export
options you want to apply (see allExportPresets). You then configure the export session to specify the
output URL and file type, and optionally other settings such as the metadata and whether the output should
be optimized for network use.
Export preset
You can check whether you can export a given asset using a given preset using
exportPresetsCompatibleWithAsset: as illustrated in this example:
Using Assets
Trimming and Transcoding a Movie
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
15AVAsset *anAsset = <#Get an asset#>;
NSArray *compatiblePresets = [AVAssetExportSession
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:anAsset presetName:AVAssetExportPresetLowQuality];
// Implementation continues.
You complete configuration of the session by providing the output URL (The URL must be a file URL.)
AVAssetExportSession can infer the output file type from the URL's path extension; typically, however,
you set it directly using outputFileType. You can also specify additional properties such as the time range,
a limit for the output file length, whether the exported file should be optimized for network use, and a video
composition. The following example illustrates how to use the timeRange property to trim the movie:
exportSession.outputURL = <#A file URL#>;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = CMTimeMakeWithSeconds(1.0, 600);
CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
To create the new file you invoke exportAsynchronouslyWithCompletionHandler:. The completion
handler block is called when the export operation finishes; in your implementation of the handler, you should
check the session's status to determine whether the export was successful, failed, or was canceled:
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed: %@", [[exportSession error]
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export canceled");
Using Assets
Trimming and Transcoding a Movie
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
You can cancel the export by sending the session a cancelExport message.
The export will fail if you try to overwrite an existing file, or write a file outside of the application's sandbox. It
may also fail if:
● There is an incoming phone call
● Your application is in the background and another application starts playback
In these situations, you should typically inform the user that the export failed, then allow the user to restart
the export.
Reading and Writing Assets
You use an AVAssetReader when you want to perform an operation on the contents of an asset. For example,
you might read the audio track of an asset to produce a visual representation of the waveform. To produce an
asset from media such as sample buffers or still images, you use an AVAssetWriter object.
You can use an asset reader and asset writer object in tandem to convert an asset from one representation to
another. Using these objects you have more control over the conversion than you do with AVExportSession.
For example of you want to choose which of the tracks you want to be represented in the output file, specify
your own output format, or modify the asset during the conversion process.
Using Assets
Reading and Writing Assets
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
17To control the playback of assets, you use an AVPlayer object. During playback, you can use an AVPlayerItem
object to manage the presentation state of an asset as a whole, and an AVPlayerItemTrack to manage the
presentation state of an individual track. To display video, you use an AVPlayerLayer object.
Playing Assets
A player is a controller object that you use to manage playback of an asset, for example starting and stopping
playback, and seeking to a particular time. You use an instance of AVPlayer to play a single asset. On iOS 4.1
and later, you can use an AVQueuePlayer object to play a number of items in sequence (AVQueuePlayer is
a subclass of AVPlayer).
A player provides you with information about the state of the playback so, if you need to, you can synchronize
your user interface with the player's state. You typically direct the output of a player to specialized Core
Animation Layer (an instance of AVPlayerLayer or AVSynchronizedLayer). To learn more about layers,
see Core Animation Programming Guide .
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
PlaybackMultiple player layers: You can create arbitrarily many AVPlayerLayer objects from a single
AVPlayer instance, but only the most-recently-created such layer will display any video content
Although ultimately you want to play an asset, you don't provide assets directly to an AVPlayer object. Instead,
you provide an instance of AVPlayerItem. A player item manages the presentation state of an asset with
which it is associated. A player item contains player item tracks—instances of AVPlayerItemTrack—that
correspond to the tracks in the asset.
AVPlayerItemTrack AVPlayer AVPlayerLayer
This abstraction means that you can play a given asset using different players simultaneously, but rendered
in different ways by each player. Using the item tracks, you can, for example, disable a particular track during
playback (you might not want to play the sound component).
AVPlayer 1 AVPlayer 2
• Video
• Audio R
• Audio L
AVPlayerItem 1 AVPlayerItem 2
time = 4:15 time = 2:10
Audio R
Audio L
Playing Assets
2011-10-12 | © 2011 Apple Inc. All Rights Reserved.
19You can initialize a player item with an existing asset, or you can initialize a player item directly from a URL so
that you can play a resource at a particular location (AVPlayerItem will then create and configure an asset
for the resource). As with AVAsset, though, simply initializing a player item doesn't necessarily mean it's ready
for immediate playback. You can observe (using key-value observing) an item's status property to determine
if and when it's ready to play.
Handling Different Types of Asset
The way you configure an asset for playback may depend on the sort of asset you want to play. Broadly speaking,
there are two main types: file-based assets, to which you have random access (such as from a local file, the
camera roll, or the Media Library), and stream-based (HTTP Live Stream format).
To load and play a file-based asset. There are several steps to playing a file-based asset:
● Create an asset using AVURLAsset and load its tracks using
● When the asset has loaded its tracks, create an instance of AVPlayerItem using the asset.
● Associate the item with an instance of AVPlayer.
● Wait until the item's status indicatesthat it'sready to play (typically you use key-value observing to receive
a notification when the status changes).
This approach is illustrated in "Putting it all Together: Playing a Video File Using AVPlayerLayer" (page 26).
To create and prepare an HTTP live stream for playback. Initialize an instance of AVPlayerItem using the
URL. (You cannot directly create an AVAsset instance to represent the media in an HTTP Live Stream.)
NSURL *url = [NSURL URLWithString:@"<#Live stream URL#>];
// You may find a test stream at