Core Data

There are many different ways to save and load data for your app. We’ve already been using NSUserDefaults for storing preferences and small amounts of data. For larger data sets, you can use XML files or an SQLite database. This data can then be read and written directly, but that tends to be more complicated than you’d expect.

That’s where Core Data comes in. It is a framework that allows you to manipulate your data directly in Objective-C. A lot of the setup and connection work is already taken care of, and you create your data models and relationships using a graphical interface. Behind the scenes, the actual data files can be XML, SQLite or binary, and your application will still access it in the same way.

To use Core Data in your project, you need to check the corresponding box on the New Project window. Note that this option does not appear for all project types, so make sure to pick a Master-Detail Application.

Core Data Classes

The managed object model is like the database schema. This class that contains the definitions for each of the objects that you are storing in the database. You will hardly ever create or edit this file in code, but do so visually using the .xcdatamodeld file in the project.

The persistent store coordinator is like the database connection. You use this object to set the name, type, and location of your database. Any save operation also goes through this single connection which, as its name implies, keeps all the data coordinated.

The managed object context is like the “scratch pad” for objects. Whenever you need to get, delete, or insert objects in the persistent store, you will call methods on the managed object context.

The managed object is a generic class that is at the base of any Core Data models. Think of it as NSObject for Core Data.

You will always have a single instance of the NSManagedObjectModel, NSPersistentStoreCoordinator, and NSManagedObjectContext. You will usually have many instances of many different NSManagedObject subclasses.

If we look at the App Delegate implementation in the project we just created, we can see how each of these objects is created.

First, the model is loaded from the visual file.

Then, the model is used to build a connection to the persistent store. You’ll notice that by default, this is an SQLite database stored in the application’s documents directory.

And finally, a managed context is created and linked to the persistent store coordinator.

Defining the Model

The model for the data is defined in the .xcdatamodeld file. Objects are called entities here, and they hold attributes with a name and a type. You can also create relationships linking entities together.

You build a new entity by clicking the Add Entity button at the bottom. You can then assign a set of attributes to this entity.

The entity can also have relationships to others. You can customize the type of relationship in the Data Model Inspector on the right.

In our example, a Session can have any number of Events (including none), and an Event can only be linked to one Session. Furthermore, if you delete a Session, it will automatically delete all linked Events, because we set the Delete Rule to Cascade.

Reading and Writing

We want to create a new Session every time the Master view is shown on screen. We will first check if any Sessions already exist in the store.

The first step is to build an NSFetchRequest for the requested entity.

We will then execute the request on the managed object context and retrieve all of the results in an NSArray. We can then check whether or not any Sessions exist by looking at the number of elements in the array.

If no previous Session exists, we’ll create a new one with number set to 1. Note that we use the setValue:forKey: method to set the entity attributes.

Once our new Session is created, we need to save the managed object context to the store.

If a previous Session already exists, we’ll create a new one with number set to the incremented value of whatever the last number was.

First we’ll need to sort the fetched results using an NSSortDescriptor.

We can then read the highest Session number, and use that value to build our new Session. Note that we use the valueForKey: method to read entity attributes.

We can clean up our implementation by removing duplicate code.


If you try to add a new entry to the table, the app will crash because the Event entity now requires a relationship to a Session.

First, we will add an attribute to store the current Session to our MasterViewController class.

We can then add the Session value to any newly created Event.

If we print out our fetch results, we’ll see that Events are automatically added to the Session‘s events array. This is because and Event.session are set as inverse relationships.

Strongly-Typed Models

So far, we’ve used the base NSManagedObject class to access our data, and the setValue:forKey: and valueForKey: methods for setting and getting attributes and relationships. Although this can work fine, it can lead to errors and typos as we are not getting any help from the compiler to use the correct names and types.

A better way of doing this is to create a model class for each entity.

  1. Open the .xcdatamodeld file.
  2. Select an entity.
  3. Go to the File / New / File… menu and select the NSManagedObject subclass option.

  1. This will generate and add a header and implementation file to the project.
  2. Repeat with the remaining entities.

You can now use these subclasses instead of the base NSManagedObject.

  1. Core Data Programming Guide. Apple, Sep 19 2012.
  2. Core Data on iOS 5 Tutorial. Ray Wenderlich, Apr 13 2010.


Localization is the process of making your apps work with multiple languages.

This is surprisingly a lot simpler than it sounds, and is achieved by calling special functions and through built-in Xcode support.

Download the starter project to begin.

Localizing Strings

The first step in localizing an app is to separate all the text from the code. We will move all hard-coded strings to a special .strings file. You should name this file Localizable.strings so that your app knows where to look for it. Otherwise, you’ll have to add an entry to your .plist file.

The format for each entry in the file is "Key" = "Value";.

You can then read and use this data in your app using the NSLocalizedString macro.

You can now localize this file for the English language.

  1. Select the Localizable.strings file from the Project Navigator (on the left).
  2. Click on the Make localized… button in the File Inspector (on the right).
  3. Select English as the initial localization from the menu that pops up.

Repeat the process for the hello.jpg file.

If you examine the project files in the Finder, you will notice that both files have been moved inside a folder called en.lproj. You can localize your app in 40 languages, each identified with a 2-letter code.

You can add a French localization to the app from the project’s Info tab.

Xcode will ask you which files to include in the new localization. Select all but the Storyboard.

This will copy the selected files into an fr.lproj folder.

Rename allo.jpg to hello.jpg, and replace the version in fr.lproj.

Back in Xcode, you will notice that you can now edit two versions of the localized files. Replace the contents of Localizable.strings by their French counterparts.

You can now run your app on a French language device, and it will automatically load the correct text and resources.

You can also localize the app name by adding an entry for the CFBundleDisplayName key of the InfoPlist.strings file.

Note that sometimes changes won’t load while testing because of caching issues. Make sure to delete the app from the Simulator and to clean the project in Xcode if you encounter any refresh problems.