<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://commons.oreilly.com/wiki/skins/common/feed.css?97"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality - Revision history</title>
		<link>http://commons.oreilly.com/wiki/index.php?title=Learning_Cocoa_with_Objective-C/Single-Window_Applications/Models_and_Data_Functionality&amp;action=history</link>
		<description>Revision history for this page on the wiki</description>
		<language>en</language>
		<generator>MediaWiki 1.11.0</generator>
		<lastBuildDate>Fri, 24 May 2013 08:17:26 GMT</lastBuildDate>
		<item>
			<title>Docbook2Wiki: Initial conversion from Docbook</title>
			<link>http://commons.oreilly.com/wiki/index.php?title=Learning_Cocoa_with_Objective-C/Single-Window_Applications/Models_and_Data_Functionality&amp;diff=6269&amp;oldid=prev</link>
			<description>&lt;p&gt;Initial conversion from Docbook&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Learning Cocoa with Objective-C/TOC}}&lt;br /&gt;
In the previous four chapters, we covered the front end of Cocoa applications, windows and views, and how you can use controllers behind them. Now we turn our attention to the back end—the model—and how the data functionality of an application works.&lt;br /&gt;
&lt;br /&gt;
To take full advantage of Cocoa's data-handling mechanisms, we must first explain two concepts that we didn't cover when we first introduced Objective-C and the Foundation Kit (see [[Learning Cocoa with Objective-C/Cocoa Overview and Foundation/The Cocoa Foundation Kit|Chapter 4]]): protocols and key-value coding. After covering these topics, we deal with how to connect a user interface to an underlying data model and how that model can be saved and opened.&lt;br /&gt;
&lt;br /&gt;
== Protocols ==&lt;br /&gt;
&lt;br /&gt;
Many pieces of Cocoa functionality make use of an Objective-C language feature called a ''protocol''. A protocol is simply a list of method declarations. A class is said to ''conform'' to a protocol when it provides implementations of the methods that a protocol defines.&lt;br /&gt;
&lt;br /&gt;
To help explain the concept of a protocol, think of the similarities between a waiter at a restaurant and a vending machine.&amp;lt;ref&amp;gt;Duncan waited tables for many years while in college and is thankful that nobody tried to tip him over in order to get more food or money out of him.&amp;lt;/ref&amp;gt; Even though the waiter and the vending machine are nowhere close to being similar objects from an inheritance standpoint, they can both implement methods related to serving food and taking money. Roughly, we could describe a protocol implemented by these two objects as the following methods:&lt;br /&gt;
&lt;br /&gt;
 takeOrder&lt;br /&gt;
 serveFood&lt;br /&gt;
 takeMoney&lt;br /&gt;
 returnChange&lt;br /&gt;
 complainTo&lt;br /&gt;
&lt;br /&gt;
Of course, a vending machine doesn't usually serve very tasty or nutritious food and doesn't respond very well, if at all, to complaints. Additionally, you usually have to give vending machines money before they will take your order. But let's not get caught up too much in the details of our analogy. At a very basic level, the vending machine and waiter aren't all that different from each other—at least from the point of view of the person getting food. And note that it is easy to take this protocol and find other food-service situations in which it applies, such as getting a donut from the local convenience store.&lt;br /&gt;
&lt;br /&gt;
In object-oriented programming, protocols are useful in the following situations:&lt;br /&gt;
&lt;br /&gt;
* To declare methods that other classes are expected to implement. This lets programs define methods that they will call on objects but that other developers will actually implement, and this is crucial to loading bundles and plug-ins.&lt;br /&gt;
* To declare the public interface to an object while concealing its class. This lets more than one implementation of an object &amp;quot;hide&amp;quot; behind a protocol and prevents users from using unadvertised methods.&lt;br /&gt;
* To capture similarities among classes that are not hierarchically related. Classes that are unrelated in most respects might need to implement similar methods for use by similar outside components. Protocols help formalize these relationships while preserving encapsulation.&lt;br /&gt;
&lt;br /&gt;
Objective-C defines two kinds of protocols: informal and formal. An ''informal protocol'' uses ''categories'' to list a group of methods but doesn't associate them with any particular class or implementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sidebar&amp;quot;&amp;gt;&lt;br /&gt;
'''Categories'''&lt;br /&gt;
&lt;br /&gt;
Categories are Objective-C constructs that allow you to add methods to existing classes. This lets you add functionality to undefined classes in a way that is different than inheritance. For example, the &amp;lt;tt&amp;gt;drawAtPoint:&amp;lt;/tt&amp;gt; method that we used on &amp;lt;tt&amp;gt;NSString&amp;lt;/tt&amp;gt; in [[Learning Cocoa with Objective-C/Single-Window Applications/Custom Views|Chapter 7]] is not defined in the Foundation Kit. Instead, the AppKit defines it as a category that adds methods to the &amp;lt;tt&amp;gt;NSString&amp;lt;/tt&amp;gt; class so you can draw strings into views.&lt;br /&gt;
&lt;br /&gt;
A detailed discussion of categories is beyond the scope of this book. For more information on categories, see the ''Object-Oriented Programming and the Objective-C Language'' book installed with the Developer Tools in the ''/Developer/Documentation/Cocoa /ObjectiveC''folder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A ''formal protocol'' , on the other hand, binds the list methods to a type definition that allows typing of objects by protocol name. Additionally, when a class declares that it implements a formal protocol, all of the methods of the protocol must be implemented.&lt;br /&gt;
&lt;br /&gt;
== Key-Value Coding ==&lt;br /&gt;
&lt;br /&gt;
''Key-value coding'' is a kind of shorthand. It is defined by an informal protocol used for accessing instance variables (also known as ''properties'') indirectly by using string names (known as ''keys'' ), rather than directly through the invocation of an accessor method&amp;lt;ref&amp;gt;Accessor methods, along with properties, were introduced in [[Learning Cocoa with Objective-C/Cocoa Overview and Foundation/Object-Oriented Programming with Objective-C|Chapter 3]].&amp;lt;/ref&amp;gt; or as instance variables. The key-value coding informal protocol (more accurately, the &amp;lt;tt&amp;gt;NSKeyValueCoding&amp;lt;/tt&amp;gt; protocol) is available for use by any object that inherits from &amp;lt;tt&amp;gt;NSObject&amp;lt;/tt&amp;gt;. Several Cocoa components, as well as its scripting support, take advantage of key-value coding.&lt;br /&gt;
&lt;br /&gt;
The two basic methods for manipulating objects using the key-value coding protocol are as follows:&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;valueForKey:&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Returns the value for the property identified by the key. The default implementation searches for a public accessor method based on the key name given. For example, if the key name given is ''price'', a method named &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;getPrice&amp;lt;/tt&amp;gt; will be invoked. If neither method is found, the implementation will look for an instance variable named &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; and access it directly.&lt;br /&gt;
;&amp;lt;tt&amp;gt;takeValue:forKey:&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Sets the value for the property identified by the key to the value given. For our example of ''price'', the default implementation will search for a public accessor method named &amp;lt;tt&amp;gt;setPrice&amp;lt;/tt&amp;gt;. If the method is not found, it will attempt to access the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; instance variable directly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sidebar&amp;quot;&amp;gt;&lt;br /&gt;
'''Key-Value Coding and Primitive Types'''&lt;br /&gt;
&lt;br /&gt;
The methods in the &amp;lt;tt&amp;gt;NSKeyValueCoding&amp;lt;/tt&amp;gt; protocol work only with objects. Therefore, if you have properties that deal in numbers, you need to use the &amp;lt;tt&amp;gt;NSNumber&amp;lt;/tt&amp;gt; class instead of primitive types such as &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;double&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== A Key-Value Coding Example ===&lt;br /&gt;
&lt;br /&gt;
To show key-value coding in action, we will create a simple example based on a &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; class. By now, you should be familiar with what you'll see in this example, except for how we use key-value coding. Perform the following steps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Create a new Foundation Tool in Project Builder (File → New Project → Tool → Foundation Tool) named &amp;quot;keyvaluecoding&amp;quot;, and save it in your ''~/LearningCocoa''folder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Create a new Objective-C class named &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; (File → New File → Cocoa → Objective-C Class), as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-1|Figure 9-1]]. Be sure to create both the ''.h'' and ''.m'' files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-1&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-1. Creating the FoodItem class'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt301.png|Creating the FoodItem class]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Edit the ''FoodItem.h''file as follows:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 @interface FoodItem : NSObject {&lt;br /&gt;
 '''    NSString * name;                                              // a'''&lt;br /&gt;
                         '''    NSNumber * price;                                             // b'''&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 '''- (NSString *)name;                                               // c'''&lt;br /&gt;
                         '''- (void)setName:(NSString *)aName;                                // d'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (NSNumber *)price;                                              // e'''&lt;br /&gt;
                         '''- (void)setPrice:(NSNumber *)aPrice;                              // f'''&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&lt;br /&gt;
This code adds the following things:&lt;br /&gt;
&lt;br /&gt;
# The &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; instance variable of type &amp;lt;tt&amp;gt;NSString&amp;lt;/tt&amp;gt;. This variable will store the name of the food item.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; instance variable of type &amp;lt;tt&amp;gt;NSNumber&amp;lt;/tt&amp;gt;. This variable will store the price of the food item.&lt;br /&gt;
# Accessor method that returns the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; of the food item.&lt;br /&gt;
# Accessor method that allows the name of the food item to be set.&lt;br /&gt;
# Accessor method that returns the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; of the food item.&lt;br /&gt;
# Accessor method that allows the price of the foot item to be set.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Edit the ''FoodItem.m''file as follows:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;quot;FoodItem.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 @implementation FoodItem&lt;br /&gt;
 &lt;br /&gt;
 '''- (id)init                                                         // a'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    [super init];'''&lt;br /&gt;
                         '''    [self setName:@&amp;quot;New Item&amp;quot;];'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [self setPrice:[NSNumber numberWithFloat:0.0]];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''    return self;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (NSString *)name                                                 // b'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    return name;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (void)setName:(NSString *)newName                                // c'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    [newName retain];'''&lt;br /&gt;
                         '''    [name release]'''&lt;br /&gt;
                         '''    name = newName;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (NSNumber *)price                                                // d'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    return price;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (void)setPrice:(NSNumber *)newPrice                              // e'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    [newPrice retain];'''&lt;br /&gt;
                         '''    [price release];'''&lt;br /&gt;
                         '''    price = newPrice;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
 @end &lt;br /&gt;
&lt;br /&gt;
The code we added performs the following tasks:&lt;br /&gt;
&lt;br /&gt;
# Initializes the object with some default values.&lt;br /&gt;
# Implements the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; accessor method.&lt;br /&gt;
# Implements the &amp;lt;tt&amp;gt;setName:&amp;lt;/tt&amp;gt; accessor method. Notice that we retain the new object, release the old one, then set the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; variable to the new object, in accordance with the rules we discussed in [[Learning Cocoa with Objective-C/Cocoa Overview and Foundation/The Cocoa Foundation Kit|Chapter 4]].&lt;br /&gt;
# Implements the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; accessor method.&lt;br /&gt;
# Implements the &amp;lt;tt&amp;gt;setPrice:&amp;lt;/tt&amp;gt; accessor method.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Edit the ''main.m''file (located in the ''Sources'' folder in Project Builder's left pane) as follows:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
 '''#import &amp;quot;FoodItem.h&amp;quot;'''&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main (int argc, const char * argv[]) {&lt;br /&gt;
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;'''&amp;lt;nowiki&amp;gt;    FoodItem * candyBar = [[FoodItem alloc] init];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
 &lt;br /&gt;
                         '''    [candyBar takeValue:@&amp;quot;Aero&amp;quot; forKey:@&amp;quot;name&amp;quot;];'''&lt;br /&gt;
 '''                 // a'''&lt;br /&gt;
                         '''    [candyBar takeValue:[NSNumber numberWithFloat:1.25] forKey:@&amp;quot;price&amp;quot;]; // b'''&lt;br /&gt;
 &lt;br /&gt;
                         '''    NSLog(@&amp;quot;item name: %@&amp;quot;, [candyBar valueForKey:@&amp;quot;name&amp;quot;]);              // c'''&lt;br /&gt;
                         '''    NSLog(@&amp;quot;    price: %@&amp;quot;, [candyBar valueForKey:@&amp;quot;price&amp;quot;]);             // d'''&lt;br /&gt;
                         '''    [candyBar release];                                                   // e'''&lt;br /&gt;
     &lt;br /&gt;
     [pool release];&lt;br /&gt;
     return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The code that we added performs the following tasks:&lt;br /&gt;
&lt;br /&gt;
# Instructs the &amp;lt;tt&amp;gt;candyBar&amp;lt;/tt&amp;gt; object to set the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; instance variable to &amp;lt;tt&amp;gt;Aero&amp;lt;/tt&amp;gt;.&amp;lt;ref&amp;gt;Aero is a very tasty chocolate bar made in Europe by Nestlé. You can occasionally find them in the U.S. at specialty stores.&amp;lt;/ref&amp;gt;&lt;br /&gt;
# Instructs the &amp;lt;tt&amp;gt;candyBar&amp;lt;/tt&amp;gt; object to set the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; instance variable to &amp;lt;tt&amp;gt;1.25&amp;lt;/tt&amp;gt;. We use the &amp;lt;tt&amp;gt;NSNumber&amp;lt;/tt&amp;gt; class to wrap primitive types for use as objects in collections and in key-value coding.&lt;br /&gt;
# Instructs the &amp;lt;tt&amp;gt;candyBar&amp;lt;/tt&amp;gt; object to return the object assigned to the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; variable and prints it using the &amp;lt;tt&amp;gt;NSLog&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
# Instructs the &amp;lt;tt&amp;gt;candyBar&amp;lt;/tt&amp;gt; object to return the object assigned to the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; variable and prints it out using the &amp;lt;tt&amp;gt;NSLog&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
# Releases the &amp;lt;tt&amp;gt;candyBar&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the project ([[Image:Learning Cocoa with Objective-C_I_5_tt305.png|]]-S), and then build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt306.png|]]-R).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following output appears in Project Builder's console:&lt;br /&gt;
&lt;br /&gt;
 2002-04-10 15:31:57.584 Key Value Coding[1382] item name: Aero&lt;br /&gt;
 2002-04-10 15:31:57.585 Key Value Coding[1382]     price: 1.25&lt;br /&gt;
 &lt;br /&gt;
 Key Value Coding has exited with status 0.&lt;br /&gt;
&lt;br /&gt;
Obviously, for a real program of this length, using key-value coding is overkill compared to setting and retrieving the instance variables directly through accessor methods. Where key-value coding comes into its own is for hooking up model objects—those that implement logic and/or store data—to the generic view objects that Cocoa provides.&lt;br /&gt;
&lt;br /&gt;
Some of Cocoa's view components let you define an ''identifier'' attribute. When the identifier attribute is set to a property key name for a model object, the component can automatically get, display, and set the value of the property without having to know anything about its implementation. We're going to see how this works with table views in the next section.&lt;br /&gt;
&lt;br /&gt;
We're now done with this example application. Close the project in Project Builder before moving on.&lt;br /&gt;
&lt;br /&gt;
== Table Views ==&lt;br /&gt;
&lt;br /&gt;
Table views are objects that display data as rows and columns. In a table view, a row typically maps to one object in your data model, while a column maps to an attribute of the object for that row. [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-2|Figure 9-2]] shows a table view and its component parts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-2&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-2. Table view mapped to an object model'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt308.png|Table view mapped to an object model]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Model-Viewer-Controller (MVC) terms, a data source is a controller object that communicates with a model object (typically an array) and the view object. This relationship is shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-3|Figure 9-3]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-3&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-3. A data source as a controller between a model and a view'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt309.png|A data source as a controller between a model and a view]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To have their data displayed properly, model objects must implement a couple of methods from the &amp;lt;tt&amp;gt;NSTableDataSource&amp;lt;/tt&amp;gt; informal protocol:&lt;br /&gt;
&lt;br /&gt;
 - (int)'''numberOfRowsInTableView:'''(NSTableView *)tableView;&lt;br /&gt;
 &lt;br /&gt;
 - (id)'''tableView:'''(NSTableView *)tableView &lt;br /&gt;
           '''objectValueForTableColumn:'''(NSTableColumn *)tableColumn '''row:'''(int)row;&lt;br /&gt;
&lt;br /&gt;
The first method allows the table view to ask its data source how many rows of data are in the data model. The second method is used by the table view to retrieve an object value from the data model by row and column.&lt;br /&gt;
&lt;br /&gt;
== Table View Example ==&lt;br /&gt;
&lt;br /&gt;
To show how table views and models go together, we'll build a simple application to keep track of food items in a form that might be used to generate a menu. In Project Builder, create a new Cocoa Application project (File → New Project → Application → Cocoa Application) named &amp;quot;Menu&amp;quot;, and save it in your ''~/LearningCocoa''folder. Then open the ''MainMenu.nib''file (located in the ''Resources'' folder of Project Builder's left pane) in Interface Builder.&lt;br /&gt;
&lt;br /&gt;
=== Create the Interface ===&lt;br /&gt;
&lt;br /&gt;
To create the interface, perform the following steps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Title the main window &amp;quot;Menu&amp;quot; in the Window Title field of the Info window (Tools → Show Info, or Shift-[[Image:Learning Cocoa with Objective-C_I_5_tt311.png|]]-I).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Drag a table view object (&amp;lt;tt&amp;gt;NSTableView&amp;lt;/tt&amp;gt;) from the Cocoa-Data views palette, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-4|Figure 9-4]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-4&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-4. Adding a table view object to the interface'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt312.png|Adding a table view object to the interface]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Resize the table view to fill the window.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Change the Autosizing attributes so that the table view will always occupy the entire window, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-5|Figure 9-5]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-5&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-5. Changing the size attributes of the table view'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt313.png|Changing the size attributes of the table view]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configure the Table Columns ===&lt;br /&gt;
&lt;br /&gt;
The next step is to configure the columns by adjusting their width, giving them titles, and, most importantly, assigning identifiers to the columns so Cocoa's key-value coding can operate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Make the width of the columns equal. Select the leftmost column (you may have to double-click), hold the cursor over the right edge of the column so that it turns into a pair of horizontally opposed arrows, then drag the column edge so the column view is divided in half.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Double-click on the header bar for the left column and type ''Item Name'', then press Tab to move to the header bar for the right column.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Type ''Price'' as the header for the right column, then press Tab to select the left column.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Edit the Identifier field for the left column in the Attributes pane of the Info panel so it reads ''name'', as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-6|Figure 9-6]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-6&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-6. Editing the identifier attribute of a table column'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt314.png|Editing the identifier attribute of a table column]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tip&amp;quot;&amp;gt;&lt;br /&gt;
'''Tip'''&lt;br /&gt;
&lt;br /&gt;
Don't confuse the Column Title field, located at the top of the Attributes panel, with the Identifier field at the bottom of the window. These serve two entirely different purposes. The Column Title field is for the benefit of your users and should contain the title you've assigned to that column in steps 2 and 3. The Identifier is an internal programmatic name that refers to the name of the property that should be displayed in the column.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Repeat for the right column, assigning it an Identifier of ''price''.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Declare the Data Source Class ===&lt;br /&gt;
&lt;br /&gt;
A data source can be any object in your application that supplies the table view with data.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Create a subclass of &amp;lt;tt&amp;gt;NSObject&amp;lt;/tt&amp;gt;, and name it &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Instantiate the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; class (Classes → Instantiate MyDataSource).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Draw a connection from the table view object to the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; object in the Instances window. Make sure that you have selected the table view, not its surrounding scroll view before you draw the connection. The table view will turn a darker shade of gray when selected.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Select the &amp;lt;tt&amp;gt;dataSource&amp;lt;/tt&amp;gt; outlet in the Connections pane of the Info window, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-7|Figure 9-7]], and click the Connect button.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-7&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-7. Connecting the table view to MyDataSource'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt315.png|Connecting the table view to MyDataSource]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Click on &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; in the Classes tab of the ''MainMenu.nib'' window, and create the interface files (Classes → Create Files for MyDataSource).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save ([[Image:Learning Cocoa with Objective-C_I_5_tt316.png|]]-S) the nib, and return to Project Builder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create the Data Source ===&lt;br /&gt;
&lt;br /&gt;
The back end of our table will consist of two classes: the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; class that we defined in Interface Builder and the same &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; class that we created earlier in this chapter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Add the files for the &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; class to the project. Using the Finder, locate the ''FoodItem.h''and ''FoodItem.m''files (in the ''~/LearningCocoa/Key View Coding''directory), and drag them into the Other Sources folder of the Groups &amp;amp; Files panel in Project Builder. When the sheet appears to confirm your copy, ensure that the &amp;quot;Copy items&amp;quot; checkbox is selected, and then click the Add button, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-8|Figure 9-8]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-8&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-8. Adding our FoodItem class files to the Menu Project'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt317.png|Adding our FoodItem class files to the Menu Project]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open the ''MyDataSource.h'' file, and edit it to match the following code:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Cocoa/Cocoa.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 @interface MyDataSource : NSObject&lt;br /&gt;
 {&lt;br /&gt;
 '''    NSMutableArray * items;'''&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&lt;br /&gt;
The code we added in the header file simply declares a single array, named &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt;, as an instance variable. We will hold the many items to be displayed in the user interface of our application in this array.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open the ''MyDataSource.m''file, and edit it to match the following code:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;quot;MyDataSource.h&amp;quot;&lt;br /&gt;
 '''#import &amp;quot;FoodItem.h&amp;quot;'''&lt;br /&gt;
 &lt;br /&gt;
 @implementation MyDataSource&lt;br /&gt;
 '''- (id)init'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    [super init];'''&lt;br /&gt;
 &lt;br /&gt;
                         '''    // Some initial data for our interface'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    FoodItem * chimi = [[FoodItem alloc] init];                   // a&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    FoodItem * fajitas = [[FoodItem alloc] init];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
 &lt;br /&gt;
                         '''    [chimi setName:@&amp;quot;Chimichanga&amp;quot;];'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [chimi setPrice:[NSNumber numberWithFloat:8.95]];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''    [fajitas setName:@&amp;quot;Steak Fajitas&amp;quot;];'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [fajitas setPrice:[NSNumber numberWithFloat:10.95]];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    items = [[NSMutableArray alloc] init];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''    [items addObject:chimi];'''&lt;br /&gt;
                         '''    [items addObject:fajitas];'''&lt;br /&gt;
                         '''    [chimi release];'''&lt;br /&gt;
                         '''    [fajitas release];                                            // b'''&lt;br /&gt;
                         '''    return self;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (int)numberOfRowsInTableView:(NSTableView *)tableView'''         &lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    return [items count];                                         // c'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (id)tableView:(NSTableView *)tableView'''               &lt;br /&gt;
                         '''objectValueForTableColumn:(NSTableColumn *)tableColumn'''&lt;br /&gt;
                         '''            row:(int)row'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    NSString * identifier = [tableColumn identifier];             // d'''&lt;br /&gt;
                         '''    FoodItem * item = [items objectAtIndex:row];                  // e'''&lt;br /&gt;
                         '''    return [item valueForKey:identifier];                         // f'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&lt;br /&gt;
The code that we added performs the following tasks:&lt;br /&gt;
&lt;br /&gt;
# Creates a couple of sample menu items and puts them into an &amp;lt;tt&amp;gt;NSMutableArray&amp;lt;/tt&amp;gt; instance.&lt;br /&gt;
# Releases the food items, now that they are stored safely in the array.&lt;br /&gt;
# Returns the number of &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt; in the food items array. This lets the table view know how many rows contain data.&lt;br /&gt;
# Gets the &amp;lt;tt&amp;gt;identifier&amp;lt;/tt&amp;gt; of the column for which the table view wants data.&lt;br /&gt;
# Obtains the food &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; that is at the specified index in the array.&lt;br /&gt;
# Returns the value of the food item object that matches the property name of the &amp;lt;tt&amp;gt;identifier&amp;lt;/tt&amp;gt; obtained from the table column.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt320.png|]]-S), and then build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt321.png|]]-R). You should see something like [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-9|Figure 9-9]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-9&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-9. The Menu application in action'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt322.png|The Menu application in action]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Play with the application a little bit: resize the window; resize the individual table columns; reorder the table columns by dragging around the column headers. Quit the application ([[Image:Learning Cocoa with Objective-C_I_5_tt323.png|]]-Q) when you are done.&lt;br /&gt;
&lt;br /&gt;
=== Allow Modification of Table Entries ===&lt;br /&gt;
&lt;br /&gt;
When playing with our Menu application so far, you could select the items in the table, and you could even edit them. But when you try to complete editing an item name or a price by hitting Return or exiting the table cell, the edit doesn't take. To let the user edit the fields, a third method must be implemented to save changes back to the data source:&lt;br /&gt;
&lt;br /&gt;
 - (void)tableView:(NSTableView *)tableView &lt;br /&gt;
    setObjectValue:(id)object &lt;br /&gt;
    forTableColumn:(NSTableColumn *)tableColumn &lt;br /&gt;
               row:(int)row;&lt;br /&gt;
&lt;br /&gt;
Add the following method to our ''MyDataSource.m'' file after the &amp;lt;tt&amp;gt;tableView:objectValueForTableColumn:row:&amp;lt;/tt&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
                   '''- (void)tableView:(NSTableView *)tableView'''&lt;br /&gt;
                   '''   setObjectValue:(id)object'''&lt;br /&gt;
                   '''   forTableColumn:(NSTableColumn *)tableColumn'''&lt;br /&gt;
                   '''              row:(int)row'''&lt;br /&gt;
                   '''{'''&lt;br /&gt;
                   '''    NSString * identifer = [tableColumn identifier];                   // 1'''&lt;br /&gt;
                   '''    FoodItem * item = [items objectAtIndex:row];                       // 2'''&lt;br /&gt;
                   '''    [item takeValue:object forKey:identifer];                          // 3'''&lt;br /&gt;
                   '''}'''&lt;br /&gt;
                &lt;br /&gt;
&lt;br /&gt;
The code that we added does the following things:&lt;br /&gt;
&lt;br /&gt;
# Gets the &amp;lt;tt&amp;gt;identifier&amp;lt;/tt&amp;gt; of the column for which the table view wants to set data.&lt;br /&gt;
# Obtains the food &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; that is at the specified index in the array.&lt;br /&gt;
# Sets the property of the food item that matches the &amp;lt;tt&amp;gt;identifier&amp;lt;/tt&amp;gt; that we obtained in step 1.&lt;br /&gt;
&lt;br /&gt;
Now save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt326.png|]]-S). Before you can build and run the application to test the editing features, you first need to ensure that you have quit out of any running Menu application. Build and run the app again (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt327.png|]]-R) from within Project Builder. You should now be able to edit the fields in the table and have those changes made in the underlying data model.&lt;br /&gt;
&lt;br /&gt;
=== Adding Entries to the Model ===&lt;br /&gt;
&lt;br /&gt;
With an application like Menu, adding entries to the model can be useful. The following steps guide you through the process of adding this functionality to the application:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;We're going to add a button to the interface. To enable a new row to be added when this button is pushed, we'll need to add an action &amp;lt;tt&amp;gt;newButtonPressed:&amp;lt;/tt&amp;gt; and an outlet &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt;. An easy way to do this is to add the declarations yourself in the code. In Project Builder, edit the ''MyDataSource.h'' file to match the following code. The code you need to add is shown in '''boldface'''.&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Cocoa/Cocoa.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 @interface MyDataSource : NSObject&lt;br /&gt;
 {&lt;br /&gt;
     NSMutableArray * items;&lt;br /&gt;
 '''    IBOutlet NSTableView * table;'''&lt;br /&gt;
 }&lt;br /&gt;
 '''- (IBAction)newButtonPressed:(id)sender;'''&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the header file (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt329.png|]]-S).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;In Interface Builder's Classes pane, select &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt;, and reload the source file (Classes → Read MyDataSource.h). This causes Interface Builder to reparse the header file and pick up the new outlet and action.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Resize the table view to make room for a button.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Drag a button from the Cocoa-Views panel onto the interface, and change its name to New Item.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Select the table view, and reset its Autosizing attributes as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-10|Figure 9-10]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-10&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-10. Adding a button to Menu'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt330.png|Adding a button to Menu]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Control-drag a connection between the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; object in the Instances tab of the ''MainMenu.nib'' window and the table view. Connect it to the &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; outlet, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-11|Figure 9-11]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-11&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-11. Connecting the table view to the table outlet'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt331.png|Connecting the table view to the table outlet]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Control-drag a connection between the New Item button and the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; object in the Instances tab. Connect it to the &amp;lt;tt&amp;gt;newActionPressed:&amp;lt;/tt&amp;gt; button, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-12|Figure 9-12]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-12&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-12. Connecting the button to the data source'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt332.png|Connecting the button to the data source]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the nib file (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt333.png|]]-S), and return to Project Builder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Edit the ''MyDataSource.m'' file, adding the &amp;lt;tt&amp;gt;newButtonPressed:&amp;lt;/tt&amp;gt; method shown in the following code:&lt;br /&gt;
&lt;br /&gt;
                         '''- (IBAction)newButtonPressed:(NSEvent *)event {'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    FoodItem * item = [[FoodItem alloc] init];                     // a&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
 &lt;br /&gt;
                         '''    [items insertObject:item atIndex:0];                           // b'''&lt;br /&gt;
                         '''    [item release];'''&lt;br /&gt;
                         '''    [table reloadData];                                            // c'''&lt;br /&gt;
                         '''    [table selectRow:0 byExtendingSelection:NO];                   // d'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
                      &lt;br /&gt;
&lt;br /&gt;
The code we added performs the following tasks:&lt;br /&gt;
&lt;br /&gt;
# Creates a new &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
# Inserts the new &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; object into our data model array.&lt;br /&gt;
# Instructs the table view to reload its data. This will cause the table view to call the &amp;lt;tt&amp;gt;numberOfRowsInTableView:&amp;lt;/tt&amp;gt; method again and load all the rows from the model.&lt;br /&gt;
# Selects the row we just added into the table. This highlights the new row, so the user of the application can edit it.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the project files (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt335.png|]]-S), and then build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt336.png|]]-R). When you press the New Item button, a new row should be created, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-13|Figure 9-13]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-13&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-13. Adding a new entry to our application'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt337.png|Adding a new entry to our application]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To edit the new fields, simply click in either column, and enter a new food item and price.&lt;br /&gt;
&lt;br /&gt;
== Saving Data: Coding and Archiving ==&lt;br /&gt;
&lt;br /&gt;
Virtually all applications need to make some of their objects persistent. In user-speak, this means that all applications need a way to ''save'' their data. For example, the Menu application doesn't save the state of the data model, so all changes are lost as soon as you quit the application. Cocoa applications typically use ''coding'' and ''archiving'' to store document contents and other critical application data to disk for later retrieval. Some applications may also use coding and archiving to send objects over a network to another application.&lt;br /&gt;
&lt;br /&gt;
Coding, as implemented by the &amp;lt;tt&amp;gt;NSCoder&amp;lt;/tt&amp;gt; class, takes a connected group of objects, such as the array of food items in our sample application (an ''object graph''), and serializes that data. During serialization, the state, structure, relationships, and class memberships are captured. To be serialized, an object must conform to the &amp;lt;tt&amp;gt;NSCoding&amp;lt;/tt&amp;gt; protocol (consisting of the &amp;lt;tt&amp;gt;encodeWithCoder:&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;initWithCoder:&amp;lt;/tt&amp;gt; methods).&lt;br /&gt;
&lt;br /&gt;
Archiving, as implemented by the &amp;lt;tt&amp;gt;NSArchiver&amp;lt;/tt&amp;gt; class (which extends &amp;lt;tt&amp;gt;NSCoder&amp;lt;/tt&amp;gt;), extends this behavior by storing the serialized data in a file.&lt;br /&gt;
&lt;br /&gt;
=== Adding Coding and Archiving to the Menu Application ===&lt;br /&gt;
&lt;br /&gt;
To show how to archive objects, we will modify our Menu application to save and load files that contain the list of food items. To do this, we need to hook up the File → Open and File → Save menu items, add the save and open sheet functionality, and make sure that the &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; class can be archived.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;In Project Builder, open ''FoodItem.h'' and modify the &amp;lt;tt&amp;gt;@interface&amp;lt;/tt&amp;gt; declaration as follows. Adding &amp;lt;tt&amp;gt;&amp;lt;NSCoding&amp;gt;&amp;lt;/tt&amp;gt; declares that the &amp;lt;tt&amp;gt;Song&amp;lt;/tt&amp;gt; class conforms to the coding protocol.&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 @interface FoodItem : NSObject '''&amp;lt;NSCoding&amp;gt;''' {&lt;br /&gt;
     NSString * name;&lt;br /&gt;
     NSNumber * price;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 .&lt;br /&gt;
 .&lt;br /&gt;
 .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NSCoding&amp;lt;/tt&amp;gt; appears in brackets to signify that the &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; interface implements the coding protocol. If you were to read this declaration aloud, it would sound like: &amp;quot;&amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; extends from the &amp;lt;tt&amp;gt;NSObject&amp;lt;/tt&amp;gt; class and implements the &amp;lt;tt&amp;gt;NSCoding&amp;lt;/tt&amp;gt; protocol.&amp;quot;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open the ''FoodItem.m''file, and add the &amp;lt;tt&amp;gt;NSCoding&amp;lt;/tt&amp;gt; methods after the &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; method as follows:&lt;br /&gt;
&lt;br /&gt;
                         '''- (id)initWithCoder:(NSCoder *)coder'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    [super init];'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [self setName:[coder decodeObject]];                             // a&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [self setPrice:[coder decodeObject]];                            // b&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''    return self;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (void)encodeWithCoder:(NSCoder *)coder'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [coder encodeObject:[self name]];                                // c&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;    [coder encodeObject:[self price]];                               // d&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
                      &lt;br /&gt;
&lt;br /&gt;
The code we added performs the following tasks:&lt;br /&gt;
&lt;br /&gt;
# Decodes the next object from the &amp;lt;tt&amp;gt;coder&amp;lt;/tt&amp;gt;'s data stream and sets the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; instance variable.&lt;br /&gt;
# Decodes the next object from the &amp;lt;tt&amp;gt;coder&amp;lt;/tt&amp;gt;'s data stream and sets the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; instance variable.&lt;br /&gt;
# Encodes the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; instance variable to the &amp;lt;tt&amp;gt;coder&amp;lt;/tt&amp;gt;'s data stream.&lt;br /&gt;
# Encodes the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; instance variable to the &amp;lt;tt&amp;gt;coder&amp;lt;/tt&amp;gt;'s data stream.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open ''MyDataSource.h'', and add the following two action methods:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;lt;Cocoa/Cocoa.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 @interface MyDataSource : NSObject&lt;br /&gt;
 {&lt;br /&gt;
     NSMutableArray * items;&lt;br /&gt;
     IBOutlet NSTableView * table;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 - (IBAction)newButtonPressed:(id)sender;&lt;br /&gt;
 '''- (IBAction)save:(id)sender;'''&lt;br /&gt;
                         '''- (IBAction)open:(id)sender;'''&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the source files, and then open the ''MainMenu.nib''file in Interface Builder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Reparse the ''MyDataSource.h'' file in Interface Builder. To do this, click on the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; object in the Classes tab, and then select the Classes → Read File MyDataSource.h menu option.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Click on the File menu of the MainMenu.nib - MainMenuwindow to reveal the menu options.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Control-drag a connection from the File → Open... menu item to the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; instance in the Instances tab, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-14|Figure 9-14]]. Connect it to the &amp;lt;tt&amp;gt;open:&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-14&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-14. Connecting the Open... menu item to MyDataSource'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt341.png|Connecting the Open... menu item to MyDataSource]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Control-drag a connection from the File → Save menu item to the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; instance. Connect it to the &amp;lt;tt&amp;gt;save:&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the nib file (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt342.png|]]-S), and return to Project Builder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Add the &amp;lt;tt&amp;gt;save:&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;open:&amp;lt;/tt&amp;gt; methods to ''MyDataSource.m'', as well as two helper methods, as shown here:&lt;br /&gt;
&lt;br /&gt;
 #import &amp;quot;MyDataSource.h&amp;quot;&lt;br /&gt;
 #import &amp;quot;FoodItem.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 @implementation MyDataSource&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 .&lt;br /&gt;
 .&lt;br /&gt;
 .&lt;br /&gt;
 '''- (IBAction)save:(id)sender'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    NSSavePanel * savePanel = [NSSavePanel savePanel];                  // a'''&lt;br /&gt;
                         '''    SEL sel = @selector(savePanelDidEnd:returnCode:contextInfo:);       // b'''&lt;br /&gt;
                         '''    [savePanel beginSheetForDirectory:@&amp;quot;~/Documents&amp;quot;                    // c'''&lt;br /&gt;
                         '''                                 file:@&amp;quot;menu.items&amp;quot;'''&lt;br /&gt;
                         '''                       modalForWindow:[table window]'''&lt;br /&gt;
                         '''                        modalDelegate:self'''&lt;br /&gt;
                         '''                       didEndSelector:sel'''&lt;br /&gt;
                         '''                          contextInfo:nil];'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (void)savePanelDidEnd:(NSSavePanel *)sheet'''&lt;br /&gt;
                         '''             returnCode:(int)returnCode'''&lt;br /&gt;
                         '''            contextInfo:(void *)context'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    if (returnCode == NSOKButton) {                                     // d'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;        [NSArchiver archiveRootObject:items toFile:[sheet filename]];&amp;lt;/nowiki&amp;gt;'''&lt;br /&gt;
                         '''    }'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (IBAction)open:(id)sender'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    NSOpenPanel * openPanel = [NSOpenPanel openPanel];                  // e'''&lt;br /&gt;
                         '''    SEL sel = @selector(openPanelDidEnd:returnCode:contextInfo:);'''&lt;br /&gt;
                         '''    [openPanel beginSheetForDirectory:@&amp;quot;~/Documents&amp;quot;'''&lt;br /&gt;
                         '''                                 file:nil'''&lt;br /&gt;
                         '''                                types:nil'''&lt;br /&gt;
                         '''                       modalForWindow:[table window]'''&lt;br /&gt;
                         '''                        modalDelegate:self'''&lt;br /&gt;
                         '''                       didEndSelector:sel'''&lt;br /&gt;
                         '''                          contextInfo:nil];'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
                         '''- (void)openPanelDidEnd:(NSOpenPanel *)sheet'''&lt;br /&gt;
                         '''             returnCode:(int)returnCode'''&lt;br /&gt;
                         '''            contextInfo:(void *)contextInfo'''&lt;br /&gt;
                         '''{'''&lt;br /&gt;
                         '''    if (returnCode == NSOKButton) {'''&lt;br /&gt;
                         '''        NSMutableArray * array;                                         // f'''&lt;br /&gt;
                         '''&amp;lt;nowiki&amp;gt;        array = [NSUnarchiver unarchiveObjectWithFile:[sheet filename]];&amp;lt;/nowiki&amp;gt;''' &lt;br /&gt;
                         '''        [array retain];'''&lt;br /&gt;
                         '''        [items release];'''&lt;br /&gt;
                         '''        items = array;'''&lt;br /&gt;
                         '''        [table reloadData];'''&lt;br /&gt;
                         '''    }'''&lt;br /&gt;
                         '''}'''&lt;br /&gt;
 &lt;br /&gt;
 @end&lt;br /&gt;
&lt;br /&gt;
The code that we added does the following things:&lt;br /&gt;
&lt;br /&gt;
# Creates a new Save panel—Cocoa's standard user-interface widget for selecting where a file should be saved. The way we use the Save panel uses delegation in a manner similar to the sheet we added to the Dot View application ([[Learning Cocoa with Objective-C/Single-Window Applications/Event Handling|Chapter 8]]).&lt;br /&gt;
# Obtains the &amp;lt;tt&amp;gt;selector&amp;lt;/tt&amp;gt; for the callback method that the Save panel should use when the user has selected the file to which data will be saved.&lt;br /&gt;
# Instructs the Save panel to display itself as a sheet attached to the current window. &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; doesn't have a direct reference to the window to which the sheet should be attached, but since it does have a reference to the &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt;, we can simply ask the &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; for the &amp;lt;tt&amp;gt;window&amp;lt;/tt&amp;gt; object.&lt;br /&gt;
# Archives the &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt; array to the given file if the callback method gets a status code indicating that the user selected the file to which to save.&lt;br /&gt;
# Creates a new Open panel—Cocoa's standard user-interface widget for selecting files to open. Open panels work very much like save panels.&lt;br /&gt;
# Unarchives an &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt; object from the file selected by the user; this releases the old array assigned to the &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt; variable and assigns a retained instance of the new &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Now save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_5_tt344.png|]]-S), and then build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt345.png|]]-R).&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add a few items to your list of food items, then save ([[Image:Learning Cocoa with Objective-C_I_5_tt346.png|]]-S), and you should see the save dialog sheet slide out from the titlebar of the application window, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-15|Figure 9-15]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-15&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-15. Saving our menu list'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt347.png|Saving our menu list]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quit the application, restart it ([[Image:Learning Cocoa with Objective-C_I_5_tt348.png|]]-R), and then open ([[Image:Learning Cocoa with Objective-C_I_5_tt349.png|]]-O) the data file you just saved. All the changes you made should show up. Make sure to quit ([[Image:Learning Cocoa with Objective-C_I_5_tt350.png|]]-Q) the application when you are done.&lt;br /&gt;
&lt;br /&gt;
== Using Formatters ==&lt;br /&gt;
&lt;br /&gt;
The next task for the Menu application is to add a formatter to the Price column so that the amounts of our food items are shown using a currency format.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open ''MainMenu.nib'' in Interface Builder.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Drag a currency formatter (&amp;lt;tt&amp;gt;NSNumberFormatter&amp;lt;/tt&amp;gt;) from the Cocoa-Views palette to the price column, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-16|Figure 9-16]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-16&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-16. Adding a number formatter to the Menu application'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt351.png|Adding a number formatter to the Menu application]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;In the number-formatter inspector, set up the format to use the currency settings shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-17|Figure 9-17]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-17&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-17. The number formatter inspector'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt352.png|The number formatter inspector]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the nib file.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Return to Project Builder, and build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt353.png|]] -R). The menu interface should look like [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-18|Figure 9-18]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-18&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-18. Menu with the prices nicely formatted'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt354.png|Menu with the prices nicely formatted]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sorting Tables ==&lt;br /&gt;
&lt;br /&gt;
The last thing we will add to our Menu application is the ability for the contents of the table to be sorted when a table column header is clicked. To do this, we will rely upon the ability of Cocoa collections to be sorted using comparators. We will add comparison methods to the &amp;lt;tt&amp;gt;FoodItem&amp;lt;/tt&amp;gt; class so that an instance object can say that it should be sorted either before or after another instance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;In Interface Builder, set the data view as the delegate of the table view by Control-dragging a connection between the table view and the &amp;lt;tt&amp;gt;MyDataSource&amp;lt;/tt&amp;gt; instance object and connecting it to the delegate outlet, as shown in [[Learning Cocoa with Objective-C/Single-Window Applications/Models and Data Functionality#learncocoa2-CHP-9-FIG-19|Figure 9-19]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;learncocoa2-CHP-9-FIG-19&amp;quot;&amp;gt;&lt;br /&gt;
'''Figure 9-19. Making the data source act as the table view's delegate'''&lt;br /&gt;
&lt;br /&gt;
[[Image:Learning Cocoa with Objective-C_I_5_tt355.png|Making the data source act as the table view's delegate]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Save the nib file (File → Save or [[Image:Learning Cocoa with Objective-C_I_5_tt356.png|]]-S), and return to Project Builder.&lt;br /&gt;
&lt;br /&gt;
Open the ''FoodItem.m''file, and add the following two methods to the file after the other methods:&lt;br /&gt;
&lt;br /&gt;
                      '''- (NSComparisonResult)compareName:(FoodItem *) item                    // a'''&lt;br /&gt;
                      '''{'''&lt;br /&gt;
                      '''&amp;lt;nowiki&amp;gt;    return [name compare:[item name]];&amp;lt;/nowiki&amp;gt;'''     &lt;br /&gt;
                      '''}'''&lt;br /&gt;
 &lt;br /&gt;
                      '''- (NSComparisonResult)comparePrice:(FoodItem *) item                   // b'''&lt;br /&gt;
                      '''{'''&lt;br /&gt;
                      '''&amp;lt;nowiki&amp;gt;    return [price compare:[item price]];&amp;lt;/nowiki&amp;gt;'''              &lt;br /&gt;
                      '''}'''&lt;br /&gt;
                   &lt;br /&gt;
&lt;br /&gt;
These methods perform the following actions:&lt;br /&gt;
&lt;br /&gt;
# This method returns a comparison result by using the &amp;lt;tt&amp;gt;compare:&amp;lt;/tt&amp;gt; method of the &amp;lt;tt&amp;gt;NSString&amp;lt;/tt&amp;gt; class to compare the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; of the given object with the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; of the current instance.&lt;br /&gt;
# This method returns a comparison result by using the &amp;lt;tt&amp;gt;compare:&amp;lt;/tt&amp;gt; method of the &amp;lt;tt&amp;gt;NSNumber&amp;lt;/tt&amp;gt; class to compare the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; of the given object with the &amp;lt;tt&amp;gt;price&amp;lt;/tt&amp;gt; of the current instance.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;div&amp;gt;Open the ''MyDataSource.m'' file, and add the following method:&lt;br /&gt;
&lt;br /&gt;
                      '''- (void)tableView:(NSTableView *)tableView'''&lt;br /&gt;
                      '''    didClickTableColumn:(NSTableColumn *)tableColumn'''&lt;br /&gt;
                      '''{'''&lt;br /&gt;
                      '''    NSString * identifier = [tableColumn identifier];               // a'''&lt;br /&gt;
                      '''    if ([identifier isEqualToString:@&amp;quot;name&amp;quot;]) {'''             &lt;br /&gt;
                      '''        [items sortUsingSelector:@selector(compareName:)];          // b'''&lt;br /&gt;
                      '''    } else {'''                &lt;br /&gt;
                      '''        [items sortUsingSelector:@selector(comparePrice:)];         // c'''&lt;br /&gt;
                      '''    }'''&lt;br /&gt;
                      '''    [table reloadData];                                             // d'''&lt;br /&gt;
                      '''}'''&lt;br /&gt;
                   &lt;br /&gt;
&lt;br /&gt;
This method does the following things:&lt;br /&gt;
&lt;br /&gt;
# Obtains the &amp;lt;tt&amp;gt;identifier&amp;lt;/tt&amp;gt; from the column so that we know with which property to sort.&lt;br /&gt;
# Tells the &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt; array to sort itself using the &amp;lt;tt&amp;gt;compareName:&amp;lt;/tt&amp;gt; method of each item in the array.&lt;br /&gt;
# Tells the &amp;lt;tt&amp;gt;items&amp;lt;/tt&amp;gt; array to sort itself using the &amp;lt;tt&amp;gt;comparePrice:&amp;lt;/tt&amp;gt; method of each item in the array.&lt;br /&gt;
# Tells the &amp;lt;tt&amp;gt;table&amp;lt;/tt&amp;gt; view that the underlying data has changed and that it needs to reload itself.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Build and run the application (Build → Build and Run, or [[Image:Learning Cocoa with Objective-C_I_5_tt359.png|]]-R). Add a few items to the Menu, and then sort by name, then price, and see the results.&lt;br /&gt;
&lt;br /&gt;
== Exercises ==&lt;br /&gt;
&lt;br /&gt;
# Change the title of the left column from Item Name to Food Item.&lt;br /&gt;
# Add the code necessary to display a confirmation dialog box when the user tries to quit the application.&lt;br /&gt;
# Examine the code in the Menu application for memory management problems.&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</description>
			<pubDate>Fri, 07 Mar 2008 12:56:06 GMT</pubDate>			<dc:creator>Docbook2Wiki</dc:creator>			<comments>http://commons.oreilly.com/wiki/index.php/Talk:Learning_Cocoa_with_Objective-C/Single-Window_Applications/Models_and_Data_Functionality</comments>		</item>
	</channel>
</rss>