In the Model-View-Controller pattern, which is the base of any iOS app design, the Model component plays an essential role. It represents the data on which the app operates. The user indirectly interacts with it through the View component of the MVC, while the Controller mediates the communication between the Model and the View.
Core Data framework manages a hierarchy of data application specific objects and is able to persist these objects in different types of store, in a way similar to a database. However, Core Data must not be considered a simple database, its main purpose being to structure the application data in objects, manage their relationships and to provide access to these objects for the Controller component. Depending on how the application is designed, the entire Model layer of the MVC could be implemented in Core Data.
This article is the first in a series on the broad Core Data topic. It explains how to set up the Core Data support in an iOS application and shows how to create the data model underlying the real objects . In the following articles we will see how to create, fetch and display data using the Core Data API, how to make changes to the data model and migrate the data to the new structure, and how to synchronize the data using iCloud.
Core Data API
Core Data operates on a layered object structure, called Core Data stack:
Each object has a well-defined responsibility. Their instantiation is sequential, from the bottom-up, as each one depends on previously created objects.
NSManagedObjectModel: in represents the data model broken down into entities, attributes and relationships. As we’ll see later, Xcode has a built-in tool for editing the data model and visualize the objects graph. The editable model file is compiled by Xcode in a binary file with the .momd extension and added to the application bundle.
NSPersistentStore: it encapsulated a storage location, usually on the disk, but can also be in memory or a remote network location. It also defines the format for the storage file (SQLite database, binary file or atomic).
NSPersistentStoreCoordinator: it controls the access to one or several persistent stores (NSPersistentStore objects). It is initialized with the NSManagedObjectModel instance.
NSManagedObjectContext: it’s the object in the Core Data stack the most oftenly used in the application code. It is initialized with the NSPersistentStoreCoordinator instance and is invoked each time we query the data, insert or modify objects. It isn’t thread-safe, so it can only be used in the thread that created it.
NSManagedObject: even if it’s not actually part of the stack, it has to be mentioned here, because it represents a Core Data entity with its attribute and relationships, which can be accessed through the Key-Value Coding protocol (using the -valueForKey: and -setValue:forKey: methods). It is possible to subclass NSManagedObject for a Core Data entity and access the attributes and relationships directly. By subclassing NSManagedObjects we can adding functionality to our custom Core Data objects. Xcode provides a template for creating automatically NSManagedObject subclasses for a specific entity from the data model.
Enabling Core Data
The Core Data framework is not added by default to any new Xcode project.
If you create a project from scratch and know you’re going to need Core Data for the application model, you should check the Use Core Data checkbox and the framework will be added as a dependency to the project:
If you are working on an existing project that doesn’t use Core Data and you want to add support for it, you have to open the target settings and, in the Linked Frameworks and Libraries section of the General tab, add the Core Data framework:
Creating the data model
When you add Core Data at the creation of the project, Xcode automatically creates a data model definition file and inserts it into the project tree. The editable data model files extension is .xcdatamodeld.
If you have an existing project and add support for Core Data later on, you have to add the data model file manually. Xcode provides a data model file template you can select from the Core Data section:
The data model file contains the Core Data objects definition. Core Data objects are also called entities; each entity has one ore more attributes (equivalent to object properties) and can have relationships with other entities.
The Xcode editor can display the data model file in two different styles: grid view and hierarchical view. You can switch between the styles using the control at the bottom-right of the editor. While I find it easier to edit the data model in the grid view style, the hierarchical view gives an overall image of the data model and is great for visualizing the relationships between the entities.
The model I use in the sample project is pretty common in tutorials dealing with persistent data structures. The application handles three types of entities related to each other: Books, Authors and Publishers.
The first step is to create the entities in the data model definition file by clicking the Add Entity button at the bottom-left of the editor, renaming the Entity added to the list and adding the attributes in the grid view:
The entity name starts with an uppercase letter, as a class name, and the attribute name starts with a lowercase letter, as a property name. It’s mandatory to assign a data type to each attribute.
Next we create the relationships between the entities. Each relationship has a name, a target entity and, usually, an inverse relationship (going from the target to the current entity). The relationships can be configured from the Data Model inspector at the right side of the editor. For example, we can set the cardinality of the relationship (To-One or To-Many):
I will not go into more details about setting the relationships, there are many options in the Data Model inspector that should look familiar to anyone who has worked with relation databases. If you want to read further, the relationships are explained in great detail in API documentation.
Creating the Core Data Stack
The Core Data stack is a group of objects that mediate the communication between our application and the data layer.
We essentially need four objects to be able to work with Core Data:
an instance of NSManagedObjectModel, initialized with data the model definition we created in the previous chapter
an instance of NSPersistentStoreCoordinator, initialized with the previous NSManagedObjectModel instance
at least one instance of NSPersistentStore, which is the actual database file on the disk. It has to be added to the previous NSPersistentStoreCoordinator
an instance of NSManagedObjectContext, which will be used to perform operations on the actual data. It is initialized with the previous NSPersistentStoreCoordinator instance.
If the project was set to use Core Data from the beginning, Xcode automatically adds and initializes these objects in the AppDelegate. There is a lot of boilerplate code in the AppDelegate.m file handling the initialization of the Core Data stack. It lazily instantiates the three objects described above.
If we added Core Data to the project at a later stage, we have to import <CoreData/CoreData.h> file in the AppDelegate header file, add three properties and initialize them in the AppDelegate implementation file. I suggest you create a new project with the Core Data enabled and copy /paste all the Core Data related code to the AppDelegate of your project.
The reason that the Core Data stack objects are declared in the AppDelegate header file is because the application delegate object is easily accessible from any implementation file using the delegate property of the UIApplication sharedApplication singleton. Through the application delegate we have access to the managedObjectContext allowing us to operate on the Core Data objects.
In this article we’ve seen how to set up an Xcode project to support Core Data and taken the opportunity to explain what the stack is and how to create a data model for the app.
In the next blog post we’ll see how to manipulate the data. As a foretaste, you can download here a sample project that creates Book records and updates the count on the screen.