Initializing a Store and Loading Data

This article provides details of how to initialize a persistent store and to load data from an URL.

Initializing a Store

When you add a store to a persistent store coordinator, the store is initialized with initWithPersistentStoreCoordinator:configurationName:URL:options:. After a store is initialized, it receives a request from the persistent store coordinator to load its data through the load: method.

You are not required to implement initWithPersistentStoreCoordinator:configurationName:URL:options:—in some situations the default implementation will suffice. If you do need to provide additional initialization, however, you need to consider that initWithPersistentStoreCoordinator:configurationName:URL:options: is invoked both for existing stores and for new stores.

Your implementation of initWithPersistentStoreCoordinator:configurationName:URL:options: must be able to handle being initialized with a nil URL and an URL that points to a zero-length file. The latter serves as an indicator that a new store is to be constructed at the specified location and allows you to securely create reservation files in known locations which can then be passed to Core Data to construct stores.

Loading a File

The load: method is responsible for retrieving the data from the URL specified for the store and creating the necessary objects. For each element in the store, you must create:

Once all of the nodes have been created, you register them with the store using addCacheNodes:.

As an example, consider a store with the following contents:

Person,Robert,Tibbot,86349382003
Person,Jeff,Hancock,5987749473
Person,Derek,Benson,7987082467
Person,George,Andronov,7987082467

Reference Data

The reference data object is simply an object representation of the data in the store. For example, you might create an NSMutableDictionary object for each Person:

{ firstName = @"Robert", lastName = @"Tibbot", id = 86349382003 }
{ firstName = @"Jeff", lastName = @"Hancock" id = 5987749473 }
{ firstName = @"Derek", lastName = @"Benson" id = 7987082467 }
{ firstName = @"George", lastName = @"Andronov" id = 3492475026 }

Managed Object ID

You create a managed object ID using objectIDForEntity:referenceObject:, passing entity and key data for the node. You can get the entity from the managed object model associated with the store's persistent store coordinator, for example:

NSEntityDescription *personEntity =
    [[[[self persistentStoreCoordinator] managedObjectModel]
        entitiesByName] objectForKey:@"Person"];
NSManagedObjectID *moID =
    [self objectIDForEntity:personEntity referenceObject:[personDictionary objectForKey: @"id"]];

The object ID for a cache node is also the object ID for a managed object representing the cache node. It is not necessary that the key information be encoded in the reference values, but it must be unique in the set of entity instances persisted in the store and reproducibly derivable.

Cache node

You create a cache node using the NSAtomicStoreCacheNode method initWithObjectID:.

NSAtomicStoreCacheNode *personNode =
                [[NSAtomicStoreCacheNode alloc] initWithObjectID:moID];

After creating each node, you usually push the corresponding persisted data into the node (although you can implement lazy loading or other behavior).

The cache node uses a mutable dictionary as a backing store. If when you parse the data you create instances of NSMutableDictionary to represent each element, and the keys in the dictionary are the property names of the corresponding entity, then you can set the cache node directly:

[personNode setPropertyCache:personDictionary];

The values in cache node must be:

  • For an attribute value, instance of an attribute type supported by Core Data (see NSAttributeDescription);

  • For a to-one relationship, another cache node instance;

  • For a to-many relationship, a collection of the related cache nodes.

Example

Consider a store with the following contents:

Person::first:Robert:last:Tibbot:id:86349382003
Person::first:Jeff:last:Hancock:id:5987749473
Person::first:Derek:last:Benson:id:7987082467
Person::first:George:last:Andronov:id:7987082467

The load: method might first parse the file to create an NSMutableDictionary object for each Person:

{ firstName = @"Robert", lastName = @"Tibbot", id = 86349382003 }
{ firstName = @"Jeff", lastName = @"Hancock", id = 5987749473 }
{ firstName = @"Derek", lastName = @"Benson", id = 7987082467 }
{ firstName = @"George", lastName = @"Andronov", id = 3492475026 }

and collect them in an array, personDictionaries. In this case, the keys used in the dictionary are the same as the property names for the Person entity.

You then create the Core Data objects as follows:

NSEntityDescription *personEntity =
    [[[[self persistentStoreCoordinator] managedObjectModel]
        entitiesByName] objectForKey:@"Person"];
 
NSMutableSet *cacheNodes = [NSMutableSet set];
 
NSDictionary *objectData;
id referenceObject;
NSManagedObjectID *moID;
NSAtomicStoreCacheNode *personNode;
 
for (NSMutableDictionary *personDictionary in personDictionaries) {
 
    objectData = [personDictionary mutableCopy];
    // The managed object itself should not store the value of the identifier as a property.
    referenceObject = [personDictionary valueForKey:@"id"];
    [objectData removeObjectForKey: @"id"];
    moID = [self objectIDForEntity:personEntity
                                referenceObject:referenceObject];
 
    personNode = [[NSAtomicStoreCacheNode alloc] initWithObjectID:moID];
    [personNode setPropertyCache:objectData];
    [cacheNodes addObject:personNode];
}
 
[self addCacheNodes:cacheNodes];