Cocoa Dev Central . Articles . Build a Core Data App Email Feedback

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

Data Model
User Interface

Create a New Project
1 of 22

Open Xcode 2.0 and Choose File > New Project. The window shown below will appear:

New Project

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.

Open Model File
 
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.

New Entity

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
Between the top and bottom portions of the modeler window, there's a small plus button. Click it once to create a new Entity.

2
Double-click the default name "Entity" in the table row and rename it to Post.

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.

New Attribute

Make sure the Post Entity is selected the far left table view.

1
Click the plus button under the Properties pane and select Add Attribute from the popup menu

2
Double-click "newAttribute" in the table view and rename it to body.

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.

Configure Attribute

1
Uncheck "Optional"

2
Choose String from the Type dropdown. 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:

Title Attribute

Next, add an Attribute called creationDate. Choose Date from the type dropdown. Make sure that the Optional checkbox stays checked in this case:

Creation Date Attribute

We now have a Entity, called Post, which has three Attributes: body, creationDate and title.

Create the Author Entity
6 of 22
Author Entity

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
Rename the Entity to Author

Add Attributes to Author

Add the two following Attributes to Author:

Author Entity

A
Create an attribute called name with a type of String, and deactivate the Optional checkbox.

B
Create an attribute called email with a type of String.


The graphical model should look like the one above.

Create the Topic Entity
7 of 22
Author Entity

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
Rename the Entity to Topic


Add an Attribute to Topic

Author Entity

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

Let's review what we have done so far.

Data Model Tasks

A
Launched Xcode, and chose File > New Project. We selected Core Data Application and named the project "BlogDemo".

B
Created the Post Entity
  • represents a post to the blog
  • attributes: body, title, creationDate

C
Created the Author Entity
  • tracks who creates each post
  • attributes: name, email

D
Created the Topic Entity
  • used to organize posts
  • attributes: title

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.

Author Entity

1
Click the plus button in and select Add Relationship from the popup menu. Note how the Kind column says "Relationship".

2
Rename the "newRelationship" to "author"

3
Choose the Author Entity from the Destination dropdown.


Author Relationship

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.

Posts Relationship

1
Click the plus button in the center pane and select Add Relationship

2
Rename the relationship to "posts" (plural)

3
Choose Post from the Destination dropdown

4
Activate the To-Many Relationship checkbox. This means that every author will have multiple posts.


Post Relationship

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.

Posts Relationship

1
Select the posts Relationship

2
Select "author" from the Inverse dropdown


Inverse Relationship

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
The last Relationship to create is a link between Post and Topic. The following steps are nearly identical to the previous tasks involving Relationships.

A
Select the Post Entity and click the plus button under the Properties pane. Choose Add Relationship

B
Rename the Relationship to "topic". Choose Topic from the Destination dropdown

C
Select the Topic Entity and click the plus button under the Properties pane. Choose Add Relationship

D
Rename the Relationship to "posts" (plural). Choose Post from the Destination dropdown

E
Activate the To-Many Relationship checkbox

F
Select "topic" from the Inverse dropdown

Review

Let's review what we just did. Remember that a Relationship is a link between two entities.

Data Model Tasks

A
Created a Relationship from Post to Author
  • tracks who creates a given blog post

B
Created a Relationship from Author to Post
  • tracks all blog posts by a given author
  • to-many relationship

C
Created the Inverse Relationship
  • combines the other two relationships

D
Created a Relationship from Post to Topic
  • associates a topic with a post

Created a Relationship from Topic to Post
  • tracks all blog posts on a given topic
  • to-many relationship

Created the Inverse Relationship
  • combines the other two relationships

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
Select MainMenu.nib in Xcode and press the Delete key. 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.

C
Drag the new MainMenu.nib into the Xcode project's Resources group, above the other items in that folder. Accept the default settings for adding the file to the project.

D
Double-click the new MainMenu.nib file in Xcode to open it in Interface Builder


The contents of the NIB file is shown below.

BlogDemo Interface

1
The Posts table. The blog posts will be listed here by title.

2
Detail view. This is where the contents of the selected Post will appear.

3
The Author configuration table. Add, edit and delete Authors here.

4
The Topic configuration table


The NIB document window looks like this:
BlogDemo NIB File

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
Add Array Controller

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

2
Double-click the title to rename it to "Posts"

Configure the Controller
14 of 22
Configure Array Controller

1
Select the Posts NSArrayController and bring up the attributes section of Interface Builder's inspector window

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
Click the Entity radio button

3
Type "Post" into the Entity Name text field

4
Activate the "Automatically prepares content" checkbox

Add Bindings

Choose "Bindings" from the dropdown at the top of the inspector window to setup bindings for the array controller.

Controller Bindings

1
Bind managedObjectContext to BlogDemoAppDelegate

2
Set the Model Key Path to "managedObjectContext"

3
Make sure the Bind checkbox is 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
Create a new NSArrayController and name it "Authors" (plural)

B
Select Entity for the mode, set the Entity Name to "Author" (singular)

C
Activate the Automatically prepares content checkbox

D
Bind managedObjectContext to BlogDemoAppDelegate

E
Set the Model Key Path to "managedObjectContext"

F
Make sure the Bind checkbox is activated

For the Topic Entity:

A
Create a new NSArrayController and name it "Topics" (plural)

B
Select Entity for the mode, set the Entity Name to "Topic" (singular)

C
Activate the Automatically prepares content checkbox

D
Bind managedObjectContext to BlogDemoAppDelegate

E
Set the Model Key Path to "managedObjectContext"

F
Make sure the Bind checkbox is activated


The end result should look like this:
All Controllers
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

Controller Bindings

A
Hold down the Control key and drag a connection from the plus button to the Posts array controller, approving a connection to the add: action

B
Control-drag a connection from the minus button to the Posts array controller, and approve a connection to the remove: action

Bind the Text Boxes

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
Added a prebuilt MainMenu.nib file to the project

B
Added and configured three NSArrayControllers, one for each Entity in BlogDemo

C
Bound the main table view's column to the Posts NSArrayController

D
Connected the buttons to the add: and remove: actions on the Posts NSArrayController

E
Bound the title and body text boxes to their respective Attributes values

Try it Out
17 of 22
Test Run

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.

Controller Bindings

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
Controller Bindings

Table Column: value
Bind to: Topics
Controller Key: arrangedObjects
Model Key Path: title

1
Open the Topics panel, and select the table column

2
Bind the value key as shown in the table to the right

3
Control-drag a connection from the plus button to the Topics array controller, approving a connection to the add: action

4
Control-drag a connection from the minus button to the 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

Now, repeat the same process for the Authors panel.

A
Bind the value key of both the name and email columns as shown in the table to the right

B
Hold down the Control key and drag a connection from the plus button to the Authors array controller, approving a connection to the add: action

C
Control-drag a connection from the minus button to the Authors array controller, and approve a connection to the remove: action

Compile and Run
20 of 22
Test Run

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.

Test Run

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
Change BlogDemo.xml to BlogDemo.blogdemodoc

B
Change NSXMLStoreType to NSSQLiteStoreType

Using a Binary Store

A
Change BlogDemo.xml to BlogDemo.blogdemodoc

B
Change NSXMLStoreType to 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.

Wrap Up
Finished BlogDemo project for Xcode 2.0

This tutorial was designed to get your first Core Data app running as quickly as possible. If you'd like to better understand how Core Data is architected, take a look at the Core Data Class Overview article.

As always, let us know what you think about the tutorial.

Further Reading

Local Page Core Data Class Overview explanations for each of the Core Data classes
Remote Site Cocoa Dev Central blog author's personal site
Apple Multi-Document Core Data Tutorial a walkthrough of an NSPersistentDocument application
Apple Core Data Programming Guide official overview docs for Core Data