written / illustrated by Scott Stevenson Cocoa has been refined dramatically over the years, but no one technology has brought such sweeping advances as Core Data. Using the Core Data framework, you can create a suprisingly sophisticated application before you write your first line of code. Your first thought might be that that writing less code means that you don't have a "real" Cocoa app, but this isn't the case. Core Data simply provides pre-built classes and tools for data management. You build your custom code on top of this basic set of functionality. Core Data is the result of Apple's extensive experience in development tools. It's a real, industrial-strength framework, and builds heavily on technologies introduced in Panther, such as Cocoa Bindings. Although Core Data makes certain things easy, it is not designed for novices. You should at least be familiar with creating a basic Cocoa application and Objective-C syntax before reading this tutorial.

Table of Contents

Create a New Project 1 of 22

Open Xcode 2.0 and Choose File > New Project. The window shown below will appear: Choose Core Data Application from the Application group and click the Next button. Name the project BlogDemo. It's important to use this exact name. Open the Data Model File In Xcode, open the Models group and double-click the BlogDemo_DataModel.xcdatamodel file, as shown below. The data modeler window will open but will be blank.

Create an Entity 2 of 22

An Entity is similar to a class. In BlogDemo, the Post Entity represents a post on a blog site. Each Post has a title, a body, a creation date, and an author. In a traditional Cocoa application, we would create a Post class, then add code to make it work. Since this is a Core Data application, we'll make a Post Entity instead. An Entity is different from a class in that it doesn't contain code. It's just a description of data. Core Data uses this description to decide how the application should behave. 1 Entity . Between the top and bottom portions of the modeler window, there's a small plus button. Click it once to create a new 2 Post. Double-click the default name "Entity" in the table row and rename it to

Add an Attribute 3 of 22

Just as an Entity is similar to a class, a Property is similar to an instance variable. There are three kinds of Properties, but the only one you need to know about for now is Attribute. An Attribute holds a single value. An Attribute also has a type associated with it, such as string, number or date. Unlike an instance variable, there is a fixed list of types that an Attribute can be. This is similar to how SQL databases have column types. Make sure the Post Entity is selected the far left table view. 1 Add Attribute from the popup menu Click the plus button under the Properties pane and selectfrom the popup menu 2 body. Double-click "newAttribute" in the table view and rename it to The body Attribute is now part of the Post Entity.

Configure the Attribute 4 of 22

The third section of the modeler window allows you to fine-tune settings on a particular Attribute. Select the body attribute to display the third section of the modeler window. 1 Uncheck "Optional" 2 String from the Type dropdown. This displays options specific to the String type. Choosefrom the. This displays options specific to the String type. 3 Set the default value to "Body Text"

Add More Attributes 5 of 22

Create another Attribute called title. Use the same options as you did for body, but set the default value to "Title" instead: Next, add an Attribute called creationDate. Choose Date from the type dropdown. Make sure that the Optional checkbox stays checked in this case: We now have a Entity, called Post, which has three Attributes: body, creationDate and title.

Create the Author Entity 6 of 22

Every blog post has an author associated with it, so let's create an Author Entity. 1 Click the plus button at the bottom of the Entity table 2 Author Add Attributes to Author Rename the Entity to Add the two following Attributes to Author: A name with a type of String, and deactivate the Optional checkbox. Create an attribute calledwith a type of, andthe Optional checkbox. B email with a type of String.

Create an attribute calledwith a type of The graphical model should look like the one above.

Create the Topic Entity 7 of 22

We want to have topics for posts to the blog. We could add a topic Attribute to Post, but a creating a separate Topic Entity will give us the option of making changes to topics without editing each individual post. 1 Once again, click the plus button at the bottom of the Entity table 2 Topic

Add an Attribute to Topic Rename the Entity to Add a single Attribute to Topic. Name it title with a type of String, and deactivate the Optional checkbox. This may seem like a simplistic Entity, but we can always add to it later.

Review

Add a Relationship 8 of 22

We now have three Entities, but they have no connection to each other. An Attribute can only represent a single value, such as a string, a date, or a number. To create a link between two Entities, we need to use another kind of Property, called a Relationship. Relationship is a link between two Entities. We will create a link from Post to Author, so that our application can keep track of who created a blog post. First, select the Post Entity so that all of its properties are visible in the center pane. 1 Add Relationship from the popup menu. Note how the Kind column says "Relationship". Click the plus button in and selectfrom the popup menu. Note how the Kind column says "Relationship". 2 Rename the "newRelationship" to "author" the "newRelationship" to "author" 3 Author Entity from the Destination dropdown.

Choose theEntity from the The graphical view should now look like the image to the right. The arrow tells us that the Relationship is a link from a post to an author. Although it looks like the arrow is pointing at the email Attribute, a Relationship always points to an Entity. The points at which the arrow connects to the entity box is somewhat arbitrary.

Add Another Relationship 9 of 22

Just as we want to keep track of the author of each blog post, we want to track all the posts for each author. We need to create a Relationship from Author to Post. In other words, the mirror image of the other Relationship. First, select the Author Entity so that all of its properties are shown in the center pane.

1 Add Relationship Click the plus button in the center pane and select 2 Rename the relationship to "posts" (plural) the relationship to "posts" (plural) 3 Post from the Destination dropdown Choosefrom the 4 To-Many Relationship checkbox. This means that every author will have multiple posts.

Activate thecheckbox. This means that every author will haveposts. The graphical model should now look like the image to the right. Notice how the Relationship from Author to Post has two arrows. This indicates that it is a to-many Relationship.

Choose the Inverse Relationship 10 of 22

We now have both Relationships set up, but it seems odd to have two separate Relationships when they are just mirror images of each other. We have the Post's Author and the Author's Posts. Let's make things easier by combining them. Verify that the Author Entity is still selected so that its Properties are displayed in the center pane. 1 posts Relationship Select theRelationship 2 author" from the Inverse dropdown

Select "" from thedropdown Notice how the two Relationship lines have been combined in the graphical representation to the right. An inverse relationship doesn't just to make things more tidy, it's actually used by Core Data to maintain data integrity. Virtually all Relationships should have an inverse version. It makes writing an application much easier and provides you with features you otherwise wouldn't have.

Add the Topic Relationships 11 of 22

Relationship to create is a link between Post and Topic. The following steps are nearly identical to the previous tasks involving Relationships. The lastto create is a link betweenand. The following steps are nearly identical to the previous tasks involving Relationships. A Post Entity and click the plus button under the Properties pane. Choose Add Relationship Select theEntity and click the plus button under the Properties pane. Choose B Topic from the Destination dropdown Rename the Relationship to "topic". Choosefrom thedropdown C Topic Entity and click the plus button under the Properties pane. Choose Add Relationship Select theEntity and click the plus button under the Properties pane. Choose D Post from the Destination dropdown Rename the Relationship to "posts" (plural). Choosefrom thedropdown E To-Many Relationship checkbox Activate thecheckbox F Inverse dropdown Select "topic" from thedropdown

Review

Add the User Interface File 12 of 22

Building a user interface with all the correct sizing attributes is beyond the scope of this tutorial, so we're going to use a prebuilt NIB file. A MainMenu.nib in Xcode and press the Delete key. Choose "Delete References & Files" from the sheet that appears Selectin Xcode and press thekey. Choose "Delete References & Files" from the sheet that appears B Download either the version of the NIB for Xcode 2.2 or later, or download the NIB for Xcode 2.0/2.1. Download only one version. Once you have the file, double-click it to decompress it. Download only one version. Once you have the file, double-click it to decompress it. C Resources group, above the other items in that folder. Accept the default settings for adding the file to the project. Drag the new MainMenu.nib into the Xcode project'sthe other items in that folder. Accept the default settings for adding the file to the project. D open it in Interface Builder

Double-click the new MainMenu.nib file in Xcode to The contents of the NIB file is shown below. 1 Posts table. The blog posts will be listed here by title. Thetable. The blog posts will be listed here by title. 2 selected Post will appear. Detail view. This is where the contents of thewill appear. 3 Author configuration table. Add, edit and delete Authors here. Theconfiguration table. Add, edit and delete Authors here. 4 Topic configuration table

The NIB document window looks like this:

Theconfiguration tableThe NIB document window looks like this: The blue cube is BlogDemoAppDelegate , which replaces the MyController class found in conventional Cocoa applications. This class is automatically created and instantiated in MainMenu.nib when you create a Core Data application.

Create the Posts Controller 13 of 22

We will use Cocoa Bindings to populate the user interface. This is an easy choice because the Core Data framework is integrated with Cocoa Bindings . To use bindings, we need to add one NSArrayController instance for each Entity. Bring up the Controllers palette in Interface Builder, which is shown to the right. The NSArrayController is the icon with a series of small green boxes in a single-file line. 1 Drag the NSArrayController icon from the pallete to the document window the NSArrayController iconto the document window 2 rename it to "Posts" Double-click the title toit to "Posts"

Configure the Controller 14 of 22

1 NSArrayController and bring up the attributes section of Interface Builder's inspector window Select the Postsand bring up the attributes section of Interface Builder's IMPORTANT: The use of the word "attributes" here is just coincidental. It has no relation to the Attributes that are part of an Entity. 2 Entity radio button Click theradio button 3 Post" into the Entity Name text field Type "" into thetext field 4 Automatically prepares content" checkbox Add Bindings Activate the "" checkbox Choose "Bindings" from the dropdown at the top of the inspector window to setup bindings for the array controller. 1 managedObjectContext to BlogDemoAppDelegate Bindto 2 Model Key Path to "managedObjectContext" Set theto "managedObjectContext" 3 Bind checkbox is activated Make sure theis activated

Add Other Array Controllers 15 of 22

Repeating the previous steps, create and configure NSArrayControllers for the other entities. For the Author Entity: A NSArrayController and name it "Authors" (plural) Create a newand name it(plural) B Entity for the mode, set the Entity Name to "Author" (singular) Selectfor the mode, set the Entity Name to(singular) C Activate the Automatically prepares content checkbox D BlogDemoAppDelegate Bind managedObjectContext to E Set the Model Key Path to "managedObjectContext" F For the Topic Entity: Make sure the Bind checkbox is activated A NSArrayController and name it "Topics" (plural) Create a newand name it(plural) B Entity for the mode, set the Entity Name to "Topic" (singular) Selectfor the mode, set the Entity Name to(singular) C Activate the Automatically prepares content checkbox D BlogDemoAppDelegate Bind managedObjectContext to E Set the Model Key Path to "managedObjectContext" F

The end result should look like this: Make sure the Bind checkbox is activatedThe end result should look like this:

Setup the Main Window 16 of 22

We're going to go through this section relatively quickly, as these concepts are covered extensively in the Cocoa Bindings tutorial. Bind the Table Posts Table Column Bind to: Posts Controller Key: arrangedObjects Model Key Path: title Select the column of the Posts table. You may have to double-click the area several times to get it to appear and select it. After you have it selected, bring up the Bindings section of the Inspector Window. Bind the table column's value as shown in the table to the right. Connect the Buttons A Posts array controller, approving a connection to the add: action Hold down the Control key and drag a connection from the plus button to thearray controller, approving a connection to theaction B Posts array controller, and approve a connection to the remove: action Bind the Text Boxes Control-drag a connection from the minus button to thearray controller, and approve a connection to theaction Bind the "value" slots of the title and body text boxes as follows: Title Text Field Bind to: Posts Controller Key: selection Model Key Path: title Body Text View Bind to: Posts Controller Key: selection Model Key Path: body

In all three cases, the Model Key Path is the name of the Attribute that we want to populate the control with.

Review

Here's a quick review of the last section. A prebuilt MainMenu.nib file to the project Added afile to the project B NSArrayControllers , one for each Entity in BlogDemo Added and configured three, one for eachin BlogDemo C Posts NSArrayController Bound the main table view's column to the D add: and remove: actions on the Posts NSArrayController Connected the buttons to theandactions on the E title and body text boxes to their respective Attributes values Bound theandtext boxes to their respectivevalues

Try it Out 17 of 22

Compile and run BlogDemo. Even though we didn't write any code, you can add, modify and delete records. If you quit and re-run the application, all the data should return. Some things are clearly missing, though. The Author and Topic dropdowns don't do anything yet. The accessory panels are empty too.

Bind the Dropdowns 18 of 22

In order to assign an Author and Topic to each Post, we need to setup the bindings for the dropdown boxes.

Bind the content, contentValues and selectedObject keys for each dropdown, as shown in the tables below. Note that selectedObject key binds to a different controller than the other keys. Author Dropdown: content Bind to: Authors Controller Key: arrangedObjects Model Key Path: leave empty contentValues Bind to: Authors Controller Key: arrangedObjects Model Key Path: name selectedObject Bind to: Posts Controller Key: selection Model Key Path: author Topic Dropdown: content Bind to: Topics Controller Key: arrangedObjects Model Key Path: leave empty contentValues Bind to: Topics Controller Key: arrangedObjects Model Key Path: title selectedObject Bind to: Posts Controller Key: selection Model Key Path: topic

The idea here is to bind the selectedObject key of a dropdown to the name of a Relationship. Post has a relationship called author, so we bind selectedObject to a model key path of "author". Post also has a Relationship called topic, so we bind the selectedObject of the other dropdown to "topic".



Bind the Accessory Panels 19 of 22



Table Column: value Bind to: Topics Controller Key: arrangedObjects Model Key Path: title 1 Topics panel, and select the table column Open the, and select the table column 2 value key as shown in the table to the right Bind thekey as shown in the table to the right 3 Topics array controller, approving a connection to the add: action Control-drag a connection from the plus button to thearray controller, approving a connection to theaction 4 Topics array controller, and approve a connection to the remove: action Authors Panel Name Column: value Bind to: Authors Controller Key: arrangedObjects Model Key Path: name Email Column: value Bind to: Authors Controller Key: arrangedObjects Model Key Path: email Control-drag a connection from the minus button to thearray controller, and approve a connection to theaction Now, repeat the same process for the Authors panel. A value key of both the name and email columns as shown in the table to the right Bind thekey of both the name and email columns as shown in the table to the right B Authors array controller, approving a connection to the add: action Hold down the Control key and drag a connection from the plus button to thearray controller, approving a connection to theaction C Authors array controller, and approve a connection to the remove: action Control-drag a connection from the minus button to thearray controller, and approve a connection to theaction

Compile and Run 20 of 22

Compile and run BlogDemo. Now that we added bindings to the dropdowns and the acessory panels, you can create Authors and Topics and assign them to posts. If you restart the application, you'll see that all the data is still intact.

The Data File 21 of 22

Locate the BlogDemo data file in the Finder. It is placed inside your home directory, in /Users/<yourname>/Library/Application Support/BlogDemo/BlogDemo.xml Drag the XML file to the Xcode icon in the dock to view it. The format is very straightforward. The markup is clear and the element names reflect Core Data terms. If you'd like to see an overview of the file structure, open /System/Library/DTDs/CoreData.dtd. Your application should not edit the data file directly. Always use the Core Data API to make changes.

Using a Different Data Store 22 of 22

Core Data applications use XML data stores by default, but you may want to use a SQLite or even a standard Binary data store. This is easily done. Open the BlogDemoAppDelegate.m file. The data store is defined in the -managedObjectContext method, which is generated automatically when you create the project. BlogDemoAppDelegate.m url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"BlogDemo.xml"]]; ... if ([coordinator addPersistentStoreWithType: NSXMLStoreType configuration: nil URL: url options: nil error: &error]) ... Using a SQLite Store A BlogDemo.xml to BlogDemo.blogdemodoc Changeto BlogDemo.blogdemodoc B NSXMLStoreType to NSSQLiteStoreType Using a Binary Store Changeto NSSQLiteStoreType A BlogDemo.xml to BlogDemo.blogdemodoc Changeto BlogDemo.blogdemodoc B NSXMLStoreType to NSBinaryStoreType

Changeto NSBinaryStoreType Core Data projects default to using .xml, .sql and .binary, but it's strongly recommended that you change this to an extension unique to your application, such as .blogdemodoc for BlogDemo.



Also, keep in mind once you change the store type to something other than XML, you will not be able to make changes to your data model as easily.



In particular, the tables for the SQLite store are created once, so if you change your entities after the file has been created, you will see errors about invalid columns. At that point, you must delete the SQLite data file so it can be recreated. It's generally easier to use the XML store type during development.



For more information on changes to data models, see this page. Data Store Differences The XML store is most useful during the prototyping phase, when you want to quickly glance at the data that's being written to disk. It doesn't scale well, though. The Binary store is generally faster than the XML store, but can't be easily read in a text editor. The SQLite store is generally the fastest and most scalable store. The Binary and XML stores have to load the entire contents of their data files at startup, but the SQLite store can load and unload data as needed. This can significantly shorten startup time and conserve memory. You can inspect the contents of the data file using the command line tool, found at /usr/bin/sqlite3. The only drawback of the SQLite store is that it appears to be somewhat slower than the Binary store during an initial save.