Core Data Introduction
- Properties List / NSUserDefaults: We can easily persist a lot of common iOS data structures (like NSArray, NSDictionary, NSString, NSNumber, etc) in a plist file. Also we can persist custom objects through NSCoding protocol. The problem with this technique is when we handle big volumes of data, for example if we have 100 records in a plist and we want to read one of those record, we have to load the 100 records in memory first. And if we want to add a record to that list or update some of them, we need to save all records in the plist. As we get more records in a plist we are going to make more unnecessary read/write operations and bad use of memory.
- SQLite: This is more robust than the first option but is more complex to use. You can use sql syntax to get only the records that you want and update or add records without having to load all records in memory or write all records locally. The API to handle SQLite is a little complex and there isn’t an easy way to persist objects.
- Core Data: What’s Core Data? Well, basically it’s an ORM (Object-relational mapping) that provides a high level of abstraction. It uses SQLite to persist the objects and it’s available on iOS 3.0 and higher. I think it has the best of the two previous options: it’s easy to use and it’s robust.
Core Data Stack:
We are going to mention the most important classes in Core Data framework:

- Managed Object (NSManagedObject): It represents one entity’s instance. If we have an entity called Employee, one managed object represents one employee.
- Managed Object Context (NSManagedObjectContext): This is the context where the managed objects live.
- Manged Object Model (NSManagedObjectModel): It represents the data model used to do the mapping between the classes and the relational model.
- Persistent Store Coordinator (NSPersistentStoreCoordinator): This is a collection of Persistent Object Store classes.
- Persistent Object Store (NSPersistentObjectStore): It represents a storage (Core Data usually uses SQLite).
Using Core Data
In order to start using Core Data in our project we have to do the following steps:
- Add the framework CoreData.framework to the project.
- Create a Data Model with Xcode.
- Generate the data classes (those classes are subclasses of NSManagedObject.
- Create a Managed Object Model with the defined Data Model.
- Create the Persistent Store Coordinator with the created Managed Object Model and set a Persistent Object Store on it.
- Finally, create a Managed Object Context and set the created Persistent Store Coordinator.
We are going to use the created Managed Object Context to do CRUD operations (create, read, update and delete).
In the next sections we are going to describe deeper the necessary steps to get a Managed Object Context.
Creating a Data Model
The Data Model represents the entities and relationships mainly. It helps to do the mapping of the objects to the persistent store. Those are the necessary steps to create a Data Model using Xcode ver 3.2.x:
Go to the option File >> New File in the menu, select the iOS / Resource group and choose the option Data Model.

If the project already has data classes we have an option to automatically generate the data model based on that classes. We just have to select which classes we want to add to the data model.

Finally, we are going to see the tool to create our Data Model. This tool is very straightforward to use. Graphically you can create or update you Data Model.

You can see that in the Data Model that we have two entities: Team and Match. Team has an attribute called name and it has two relationships with Match. Match represents a game between two teams. It has as attributes: the date of the match, the score of both teams and it has two relationships to the entity Team. We are going to use this data model to describe some CRUD operations.
Every entity can have:
- Attributes, similar to a field in a record, you can define the type, if it’s optional or not, if it’s indexed, etc.
- Relationship with other Entities: the relationships can be 1 to 1, 1 to N.
- Fetched Properties: It’s some kind of mix between relationships and fetches.
Generating Data Classes from the Data Model
Now that we have a data model created, we can automatically create the data classes that represent the entities defined in the model. Every data class is going to represent an instance of one entity. The generated classes are subclasses of NSManagedObject class.
There are two tools to generate these data classes. One tool is integrated with Xcode and the other one it’s a third party tool called Mogenerator (http://rentzsch.github.com/mogenerator/), the main different with the Xcode tool classes is that Mogenerator creates two set of classes per entity: one for machines, one for humans. The machine class can be always be overwritten to match the data model, while the human class with humans’ work is preserved.
I’m going to describe the steps to generate the classes with Xcode ver 3.2.x:
First, We have to be in the Xcode Data Model tool and go to File >> New File in the menu and choose the group Cocoa Touch Class and select Managed Object Class. If we aren’t on the Data Model tool, we are not going to see the final Managed Object Class option.

Then we have to select the entities from the Data Model that we want to create Data Classes for.

After this we are going to have the Data Classes generated in our project.
Creating a Managed Object Context
In order to make CRUD (create, read, update, delete) operations we need an instance of a Managed Object Context. To create a Managed Object Context we need to follow these steps:
- Create a Managed Object Model with the defined Data Model.
- Create a Persistent Store Coordinator with the created Managed Object Model and set a Persistent Object Store on it.
- Finally, create a Managed Object Context and set the created Persistent Store Coordinator.
|
// 1. Create a Managed Object Model with the defined Data Model. NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
// 2. Create a Persistent Store Coordinator with the created Managed Object Model and set a Persistent Object Store on it. NSError *error = nil;
NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@”Unresolved error %@, %@”, error, [error userInfo]); abort(); }
// 3. Create a Managed Object Context and set the created Persistent Store Coordinator. NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinator]; |
Creating a Managed Object
Now we are going to create two instances for the entity Team and one instance for the entity Match. Match has two relationships with the entity Team. That represents the teams that are going to play on that match.
|
// Create a new instance of Team (NSManagedObject subclass). We have to set the Entity Name and the created Managed Object Context Team *localTeam = (Team*)[NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:managedObjectContext];
localTeam.name = @”Manchester”;
// Create another instance of Team Team *visitingTeam = (Team*)[NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:managedObjectContext];
visitingTeam.name = @”Barcelona”;
// Create an instance for Match entity with the created Teams Match *match = (Match*)[NSEntityDescription insertNewObjectForEntityForName:@"Match" inManagedObjectContext:managedObjectContext];
// We are going to use a random value to set the match’s result srandom(time(NULL));
match.scoreVisitingTeam = [NSNumber numberWithInt:random()%5]; match.scoreLocalTeam = [NSNumber numberWithInt:random()%5]; match.date = [NSDate date]; match.visitingTeam = visitingTeam; match.localTeam = localTeam;
// Persist the changes in the Managed Object Context NSError *error = nil; if (managedObjectContext != nil) { if (![managedObjectContext save:&error]) { NSLog(@”Unresolved error %@, %@”, error, [error userInfo]); abort(); } } |
Executing Fetches
In order to execute fetches we need to create a NSFetchRequest instance. We need to define an entity name, a predicate and the order of the data result. Then we use the created Managed Object Context to execute the generated NSFetchRequest instance. The Managed Object Context returns an array of NSManagedObject objects.

|
// Create a fetch request instance. NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
// Set the entity. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Match" inManagedObjectContext:managedObjectContext]; [fetchRequest setEntity:entity];
// Set the predicate (it returns all matches played by the team “Manchester”) NSPredicate *predicate = [NSPredicate predicateWithFormat:@"localTeam.name = 'Manchester' or visitingTeam.name = 'Manchester'"]; [fetchRequest setPredicate:predicate];
// Set the order criteria NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@”date” ascending:YES] autorelease]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
// Finally, execute the fetch request NSError *error = nil; NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; |
Deleting a Managed Object
In order to delete Managed Objects we need to mark the objects that we want to delete through the Managed Object Context and then persist the changes.
|
// Get the NSManagedObject instance that we want to delete Team *team = …;
// Set that NSManagedObject instance as deleted [managedObjectContext deleteObject:team];
// Persist the changes NSError *error = nil; if (![managedObjectContext save:&error]) {
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]); abort(); } |
Updating a Managed Object
In order to update Managed Objects we just have to update its attributes values and then persist the changes.
|
// Get the NSManagedObject instance that we want to update Match *match = …;
// Update some attribute match.date = [NSDate date];
// Persist the changes NSError *error = nil; if (![managedObjectContext save:&error]) {
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]); abort(); } |
Next steps
I’m going to mention some topics that you should read if you want to learn more about Core Data:
- NSFetchedResultController: This is a controller used to optimize the use of memory when we have to show information on a Table View.
- Versions and Migration: Core Data has some tools to automatically implement updates on our data model.
- Threading: It’s important to understand how to use Core Data on multithread scenarios.
References
- Core Data Tutorial for iOS
- Introduction to Core Data Programming Guide
- The frirst seven chapters from the book “More iPhone 3 Development” - Dave Mark and Jeff LaMarche.
- Book: Pro Core Data for iOS - Michel Privat and Robert Warner.