Core Data Programming Guide

Core Data FAQ

Where does a Managed Object Context Come From?

Where a managed object context comes from is entirely application-dependent. In a Cocoa document-based application using NSPersistentDocument, the persistent document typically creates the context, and gives you access to it through the managedObjectContext method.

In a single-window application, if you create your project using the standard project assistant, the application delegate (the instance of the AppDelegate class) again creates the context, and gives you access to it through the managedObjectContext method. In this case, however, the code to create the context (and the rest of the Core Data stack) is explicit. It is written for you automatically as part of the template.

Note that you should not use instances of subclasses of NSController directly to execute fetches (for example, you should not create an instance of NSArrayController specifically to execute a fetch). Controllers are for managing the interaction between your model objects and your human interface. At the model object level, you should just use a managed object context to perform the fetches directly.

How do I initialize a store with default data?

There are two issues here: creating the data, and ensuring the data is imported only once.

There are several ways to create the data.

You can create a separate persistent store that contains the default data and include the store as an application resource. When you want to use it, you must either copy the whole store to a suitable location, or copy the objects from the defaults store to an existing store.

For small datasets, you can create the managed objects directly in code.

You can create a property list—or some other file-based representation—of the data, and store it as an application resource. When you want to use it, you must open the file and parse the representation to create managed objects.

You should not use this technique on iOS, and only if absolutely necessary on OS X. Parsing a file to create a store incurs unnecessary overhead. It is much better to create a Core Data store yourself offline and use it directly in your application.

There are also several ways to ensure that the defaults are imported only once:

If you are using iOS or creating a non-document-based application for OS X, you can add a check on application launch to determine whether a file exists at the location you specify for the application’s store. If it doesn't, you need to import the data. For an iOS-based example, see CoreDataBooks.

If there is a possibility that the store (hence file) might be created but the data not imported, then you can add a metadata flag to the store. You can check the metadata (using metadataForPersistentStoreWithURL:error:) more efficiently than executing a fetch (and it does not require you to hard code any default data values).

How do I use my existing SQLite database with Core Data?

You don’t. Although Core Data supports SQLite as one of its persistent store types, the database format is private. You cannot create a SQLite database using native SQLite API and use it directly with Core Data (nor should you manipulate an existing Core Data SQLite store using native SQLite API). If you have an existing SQLite database, you need to import it into a Core Data store (see Efficiently Importing Data).

I have a to-many relationship from Entity A to Entity B. How do I fetch the instances of Entity B related to a given instance of Entity A?

You don’t. More specifically, there is no need to explicitly fetch the destination instances, you simply invoke the appropriate key-value coding or accessor method on the instance of Entity A. If the relationship is called “widgets”, then if you have implemented a custom class with a similarly named accessor method, you simply write:

How do I fetch objects in the same order I created them?

Objects in a persistent store are unordered. Typically you should impose order at the controller or view layer, based on an attribute such as creation date. If there is order inherent in your data, you need to explicitly model that.

How do I copy a managed object from one context to another?

First, note that in a strict sense you are not copying the object. You are conceptually creating an additional reference to the same underlying data in the persistent store.

To copy a managed object from one context to another, you can use the object’s object ID, as illustrated in the following example.

NSManagedObjectID *objectID = [managedObject objectID];

NSManagedObject *copy = [context2 objectWithID:objectID];

I have a key whose value is dependent on values of attributes in a related entity—how do I ensure it is kept up to date as the attribute values are changes and as the relationship is manipulated?

There are many situations in which the value of one property depends on that of one or more other attributes in another entity. If the value of one attribute changes, then the value of the derived property should also be flagged for change. How you ensure that key-value observing notifications are posted for these dependent properties depends on which version of OS X you’re using and the cardinality of the relationship.

OS X v10.5 and later for a to-one relationship

If there is a to-one relationship to the related entity, then to trigger notifications automatically you should either override keyPathsForValuesAffectingValueForKey: or implement a suitable method that follows the pattern it defines for registering dependent keys.

Or, to achieve the same result, you could just implement keyPathsForValuesAffectingFullNameAndDepartment as illustrated in the following example:

+ (NSSet *)keyPathsForValuesAffectingFullNameAndDepartment {

return [NSSet setWithObjects:@"lastName", @"firstName",

@"department.deptName", nil];

}

To-many relationships

keyPathsForValuesAffectingValueForKey: does not allow key-paths that include a to-many relationship. For example, suppose you have an Department entity with a to-many relationship (employees) to a Employee, and Employee has a salary attribute. You might want the Department entity have a totalSalary attribute that is dependent upon the salaries of all the Employees in the relationship. You can not do this with, for example, keyPathsForValuesAffectingTotalSalary and returning employees.salary as a key.

There are two possible solutions in both situations:

You can use key-value observing to register the parent (in this example, Department) as an observer of the relevant attribute of all the children (Employees in this example). You must add and remove the parent as an observer as child objects are added to and removed from the relationship (see Registering for Key-Value Observing). In the observeValueForKeyPath:ofObject:change:context: method you update the dependent value in response to changes, as illustrated in the following code fragment:

You can register the parent with the application's notification center as an observer of its managed object context. The parent should respond to relevant change notifications posted by the children in a manner similar to that for key-value observing.

In Xcode’s predicate builder, why don’t I see any properties for a fetched property predicate?

If you want to create a predicate for a fetched property in the predicate builder in Xcode, but don’t see any properties, you have probably not set the destination entity for the fetched property.

How efficient is Core Data?

Throughout the development of Core Data, the engineering team compared the runtime performance of a generic Core Data application with that of a similar application developed without using Core Data. In general, the Core Data implementation performed better. There may nevertheless be opportunities for further optimization, and the team continues to pursue performance aggressively. For a discussion of how you can ensure you use Core Data as efficiently as possible, see Core Data Performance.

Core Data looks similar to EOF. What are the differences?

Core Data and EOF (the Enterprise Objects Framework that ships with WebObjects) share a common heritage, but have different goals. EOF is a Java-based framework that connects as a client to a database server. Core Data is an Objective-C-based framework designed to support desktop application development. Core Data supports a number of features not supported by EOF, and vice-versa.

Features Supported Only by EOF

EOF allows you to use custom SQL, shared editing contexts, and nested editing contexts. Core Data does not provide the equivalent of an EOModelGroup—the NSManagedObjectModel class provides methods for merging models from existing models, and for retrieving merged models from bundles.

EOF supports pre-fetching and batch faulting of relationships, in OS X v10.4 Core Data does not. In OS X v10.5, when you create a fetch request, you can use setRelationshipKeyPathsForPrefetching: to specify key paths for relationships that should be fetched with the target entity.

Features Supported Only by Core Data

Core Data supports fetched properties; multiple configurations within a managed object model; local stores; store aggregation (the data for a given entity may be spread across multiple stores); customization and localization of property names and validation warnings; and the use of predicates for property validation.

Change Management

There is an important behavioral difference between EOF and Core Data with respect to change propagation. In Core Data, peer managed object contexts are not "kept in sync" in the same way as editing contexts in EOF. Given two managed object contexts connected to the same persistent store coordinator, and with the "same" managed object in both contexts, if you modify one of the managed objects then save, the other is not re-faulted (changes are not propagated from one context to another). If you modify then save the other managed object, then (at least if you use the default merge policy) you will get an optimistic locking failure.

Multi-Threading

The policy for locking a Core Data managed object context in a multithreaded environment is not the same policy as for an editing context in EOF.

OS X Desktop

These questions are only relevant to OS X/desktop.

How do I get the GUI to validate the data entered by the user?

Core Data validates all managed objects when a managed object context is sent a save: message. In a Core Data document-based application, this is when the user saves the document. You can have the GUI validate it as the data is being entered by selecting the “Validates Immediately” option for a value binding in the Interface Builder bindings inspector. If you establish the binding programmatically, you supply in the binding options dictionary a value of YES (as an NSNumber object) for the key NSValidatesImmediatelyBindingOption (see Binding Options).

For details of how to write custom validation methods, see the subclassing notes for NSManagedObject.

When I remove objects from a detail table view managed by an array controller, why are they not removed from the object graph?

If an array controller manages the collection of objects at the destination of a relationship, then by default the remove method simply removes the current selection from the relationship. If you want removed objects to be deleted from the object graph, then you need to enable the “Deletes Objects On Remove” option for the contentSet binding.

How do I get undo/redo for free in my non-document-architecture-based app?

In a Core Data document-based application, the standard NSDocument undo manager is replaced by the document’s managed object context’s undo manager. In a non-document-based application for desktop OS X, your window’s delegate can supply the managed object context’s undo manager using the windowWillReturnUndoManager: delegate method. If your window delegate has an accessor method for the managed object context (as is the case if you use the Core Data Application template), your implementation of windowWillReturnUndoManager: might be as follows.