Accessing the Core Data Stack

This article contains snippets for creating and accessing parts of the main pieces of infrastructure defined by the Core Data framework.

Core Data Stack Architectures

How you access the parts of the Core Data stack may depend in part on the application architecture and platform.

OS X

Broadly-speaking, in OS X there are two basic application architectures for programs that use Core Data:

  • Single-coordinator applications.

    These applications typically have a single Core Data stack (as defined by a single persistent store coordinator) managed by a single controller object. They generally use a single persistent store for the whole application.

  • Document-based applications.

    These applications typically use the Application Kit’s NSPersistentDocument class. There is a usually a persistent store coordinator and a single persistent store associated with each document.

This article uses the terms “single-coordinator application” and “document-based application” to differentiate between these architectures.

iOS

In iOS, the application delegate usually maintains a persistent store coordinator that manages the application’s store. It typically creates a managed object context, but it often doesn’t own it. This is explained in greater detail in “Getting a Managed Object Context.”

Getting a Managed Object Context

In OS X:

In iOS:

Sometimes, though, it’s easier or more appropriate to retrieve the context from somewhere other than application or the document, or the view controller. Several objects you might use in a Core Data-based application keep a reference to a managed object context. A managed object itself has a reference to its own context, as do the various controller objects that support Core Data such as array and object controllers (NSArrayController and NSObjectController in OS X, and NSFetchedResultsController in iOS).

Retrieving the context from one of these objects has the advantage that if you re-architect your application, for example to make use of multiple contexts, your code is likely to remain valid. For example, if you have a managed object, and you want to create a new managed object that will be related to it, you can ask original object for its managed object context and create the new object using that. This will ensure that the new object you create is in the same context as the original.

Creating a New Managed Object Context

You sometimes need to create a new managed object context to contain a disjoint set of edits that you might want to discard without perturbing the main context (for example, if you’re presenting a modal view to add and edit a new object).

To create a new managed object context, you need a persistent store coordinator.

NSPersistentStoreCoordinator *psc = <#Get the coordinator#>;
NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] init];
[newContext setPersistentStoreCoordinator:psc];

If you already have a reference to an existing context, you can ask it for its persistent store coordinator. This way you can be sure that the new context is using the same coordinator as the existing one (assuming this is your intent):

NSManagedObjectContext *context = <#Get the context#>;
NSPersistentStoreCoordinator *psc = [context persistentStoreCoordinator];
NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] init];
[newContext setPersistentStoreCoordinator:psc];

Getting the Managed Object Model and Entities

You sometimes need to access a managed object model to get information about a particular entity.

Applications typically have just a single model (although it may have more than one configuration). In a single-coordinator application, you typically get the model directly from the application delegate. In a document-based application, you get the model directly from the document.

If you have access to a managed object context—directly or indirectly (see “Getting a Managed Object Context”)—you can get the model from the context’s persistent store coordinator. From the model, you can retrieve an entity using entitiesByName:

NSManagedObjectContext *context = <#Get the context#>;
NSPersistentStoreCoordinator *psc = [context persistentStoreCoordinator];
NSManagedObjectModel *model = [psc managedObjectModel];
NSEntityDescription *entity = [[model entitiesByName] objectForKey:@"<#Entity name#>"];

Adding a Persistent Store

In many applications, there is only one persistent store for each persistent store coordinator. In an single-coordinator application, the store is associated with the whole application. In a document-based application, each document has a separate store. Sometimes, however, you might want to add another store. You add the store to the persistent store coordinator. You have to specify the store’s type, location, and configuration (based on configurations present on the managed object model associated with the coordinator). You can also specify other options, such as whether an old version of the store should be migrated to a current version (see Core Data Model Versioning and Data Migration Programming Guide).

In an single-coordinator applications, you can get the application’s coordinator directly from the application delegate.

In document-based applications, you can get the coordinator from the document’s managed object context.

NSPersistentStoreCoordinator *psc = <#Get the coordinator#>;
NSURL *storeUrl = [NSURL fileURLWithPath:@"<#Path to store#>"];
NSString *storeType = <#Store type#>; // A store type, such as NSSQLiteStoreType
NSError *error;
if (![psc addPersistentStoreWithType:storeType configuration:nil
    URL:storeUrl options:nil error:&error]) {
    // Handle the error.
}