Inherits from NSObject
Declared in RKManagedObjectStore.h

Overview

The RKManagedObjectStore class encapsulates a Core Data stack including a managed object model, a persistent store coordinator, and a set of managed object contexts. The managed object store simplifies the task of properly setting up a Core Data stack and provides some additional functionality, such as the use of a seed database to initialize a SQLite backed persistent store and a simple code path for resetting the store by destroying and recreating the persistent stores.

Initialization

The managed object store is designed to easily initialize a Core Data stack in a recommended configuration. A store object must always be initialized with a managed object model, but this managed object model can be directly provided, inferred from an already configured persistent store coordinator, or read from the currently available bundles within the application. Note that several features provided by the framework rely on the store being initialized with a mutable managed object model. Please refer to the documentation in the initWithManagedObjectModel: for details.

Managed Object Contexts

The managed object store provides the application developer with a pair of managed object contexts with which to work with Core Data. The store configures a primary managed object context with the NSPrivateQueueConcurrencyType that is associated with the persistent store coordinator for handling Core Data persistence. A second context is also created with the NSMainQueueConcurrencyType that is a child of the primary managed object context for doing work on the main queue. Additional child contexts can be created directly or via a convenience method interface provided by the store (see newChildManagedObjectContextWithConcurrencyType:tracksChanges:).

The managed object context hierarchy is designed to isolate the main thread from disk I/O and avoid deadlocks. Because the primary context manages its own private queue, saving the main queue context will not result in the objects being saved to the persistent store. The primary context must be saved as well for objects to be persisted to disk.

It is also worth noting that because of the parent/child context hierarchy, objects created on the main thread will not obtain permanent managed object ID’s even after the primary context has been saved. If you need to refer to the permanent representations of objects created on the main thread after a save, you may ask the main queue context to obtain permanent managed objects for your objects via obtainPermanentIDsForObjects:error:. Be warned that when obtaining permanent managed object ID’s, you must include all newly created objects that are reachable from the object you are concerned with in the set of objects provided to obtainPermanentIDsForObjects:error:. This means any newly created object in a one-to-one or one-to-many relationship must be provided or you will face a crash from the managed object context. This is due to a bug in Core Data still present in iOS5, but fixed in iOS6 (see Open Radar http://openradar.appspot.com/11478919)..)

The search additions category provides support for configuring search indexing for entities in a managed object store.

Tasks

Accessing the Default Object Store

Initializing an Object Store

  • – initWithManagedObjectModel:

    Initializes the receiver with a given managed object model. This is the designated initializer for RKManagedObjectStore.

  • – initWithPersistentStoreCoordinator:

    Initializes the receiver with an existing persistent store coordinator.

  • – init

    Initializes the receiver with a managed object model obtained by merging the models from all of the application’s non-framework bundles.

Configuring Persistent Stores

  • – createPersistentStoreCoordinator

    Creates a persistent store coordinator with the receiver’s managed object model. After invocation, the persistentStoreCoordinator property will no longer be nil.

  • – addInMemoryPersistentStore:

    Adds a new in memory persistent store to the persistent store coordinator of the receiver.

  • – addSQLitePersistentStoreAtPath:fromSeedDatabaseAtPath:withConfiguration:options:error:

    Adds a new SQLite persistent store, optionally initialized with a seed database, to the persistent store coordinator of the receiver.

  • – resetPersistentStores:

    Resets the persistent stores in the receiver’s persistent store coordinator and recreates them. If a store being reset is backed by a file on disk (such as a SQLite file), the file will be removed prior to recreating the store. If the store was originally created using a seed database, the seed will be recopied to reset the store to its seeded state. If the managed object model uses External Storage for any of its entities, then the external storage directory will be recursively deleted when the store is reset.

Retrieving Details about the Store

Working with Managed Object Contexts

Performing Migrations

RKSearchAdditions Methods

Properties

mainQueueManagedObjectContext

The main queue managed object context of the receiver.

@property (nonatomic, strong, readonly) NSManagedObjectContext *mainQueueManagedObjectContext

Discussion

The main queue context is available for usage on the main queue to drive user interface needs. The context is created with the NSMainQueueConcurrencyType and as such may be messaged directly from the main thread. The context is a child context of the persistentStoreManagedObjectContext and can persist changes up to the parent via a save.

Declared In

RKManagedObjectStore.h

managedObjectCache

The managed object cache associated with the receiver.

@property (nonatomic, strong) id<RKManagedObjectCaching> managedObjectCache

Discussion

The managed object cache is used to accelerate intensive Core Data operations by caching managed objects by one or more attributes.

Default: An instance of RKFetchRequestManagedObjectCache.

Warning: A nil managed object cache will result in a store that is unable to uniquely identify existing objects by identification attributes and may result in the creation of duplicate objects within the store.

Declared In

RKManagedObjectStore.h

managedObjectModel

Returns the managed object model of the receiver.

@property (nonatomic, strong, readonly) NSManagedObjectModel *managedObjectModel

Return Value

The managed object model of the receiver.

Declared In

RKManagedObjectStore.h

persistentStoreCoordinator

Returns the persistent store coordinator of the receiver.

@property (nonatomic, strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator

Return Value

The persistent store coordinator of the receiver.

Declared In

RKManagedObjectStore.h

persistentStoreManagedObjectContext

Returns the managed object context of the receiver that is associated with the persistent store coordinator and is responsible for managing persistence.

@property (nonatomic, strong, readonly) NSManagedObjectContext *persistentStoreManagedObjectContext

Discussion

The persistent store context is created with the NSPrivateQueueConcurrencyType and as such must be interacted with using [NSManagedObjectContext performBlock:] or [NSManagedObjectContext performBlockAndWait:]. This context typically serves as the parent context for scratch contexts or main queue contexts for interacting with the user interface. Created by the invocation of createManagedObjectContexts.

Declared In

RKManagedObjectStore.h

searchIndexer

The search indexer for the receiver’s primary managed object context.

@property (nonatomic, readonly) RKSearchIndexer *searchIndexer

Discussion

A search indexer is instantiated when search indexing is added to an entity in the receiver’s managed object model.

Declared In

RKManagedObjectStore+RKSearchAdditions.h

Class Methods

defaultStore

Returns the default managed object store for the application.

+ (instancetype)defaultStore

Return Value

The default managed object store.

Declared In

RKManagedObjectStore.h

migratePersistentStoreOfType:atURL:toModelAtURL:error:configuringModelsWithBlock:

Performs a migration on a persistent store at a given URL to the model at the specified URL.

+ (BOOL)migratePersistentStoreOfType:(NSString *)storeType atURL:(NSURL *)storeURL toModelAtURL:(NSURL *)destinationModelURL error:(NSError **)error configuringModelsWithBlock:(void ( ^ ) ( NSManagedObjectModel *model , NSURL *sourceURL ))block

Parameters

storeType

The type of store that given URL. May be nil.

storeURL

A URL to the store that is to be migrated.

destinationModelURL

A URL to the managed object model that the persistent store is to be updated to. This URL may target a specific model version with a .momd package or point to the .momd package itself, in which case the migration is performed to the current version of the model as configured on the .xcdatamodeld file used to the build the .momd package.

error

A pointer to an error object that is set in the event that the migration is unsuccessful.

block

A block object used to configure

Discussion

This method provides support for migrating persistent stores in which the source and destination models have been mutated after being loaded from the model archive on disk, such as when the RestKit managed object searching support is used. In a situation where the persistent store has been created with a dynamically modified managed object model. Core Data is unable to infer the mapping model because the metadata of the persistent store does not agree with that of the managed object model due to the dynamic modifications. In order to perform a migration, one must load the appropriate source model, apply the dynamic changes appropriate for that model, then infer a mapping model from the modified model. This method assists in this process by accepting a source store and a destination model as arguments and searching through all models in the .momd package and yielding each model to the given configuration block for processing. After the block is invoked, the metadata of the store is checked for compatibility with the modified managed object model to identify the source store. Once the source store is found, a mapping model is inferred and the migration proceeds. The migration is done against a copy of the given persistent store and if successful, the migrated store is moved to replace the original store.

To understand how this is used, consider the following example: Given a managed object model containing two entities ‘Article’ and ‘Tag’, the user wishes to configure managed object search indexing on the models and wishes to be able to migrate existing persistent stores across versions. The migration configuration would look something like this:

 NSURL *storeURL = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"MyStore.sqlite"];
 NSURL *modelURL = [[RKTestFixture fixtureBundle] URLForResource:@"VersionedModel" withExtension:@"momd"];
 BOOL success = [RKManagedObjectStore migratePersistentStoreOfType:NSSQLiteStoreType atURL:storeURL toModelAtURL:modelURL error:&error configuringModelsWithBlock:^(NSManagedObjectModel *model, NSURL *sourceURL) {
    // Examine each model and configure search indexing appropriately based on the versionIdentifiers configured in the model
    if ([[model versionIdentifiers] isEqualToSet:[NSSet setWithObject:@"1.0"]]) {
        NSEntityDescription *articleEntity = [[model entitiesByName] objectForKey:@"Article"];
        NSEntityDescription *tagEntity = [[model entitiesByName] objectForKey:@"Tag"];
        [RKSearchIndexer addSearchIndexingToEntity:articleEntity onAttributes:@[ @"title" ]];
        [RKSearchIndexer addSearchIndexingToEntity:tagEntity onAttributes:@[ @"name" ]];
    } else if ([[model versionIdentifiers] isEqualToSet:[NSSet setWithObject:@"2.0"]]) {
        NSEntityDescription *articleEntity = [[model entitiesByName] objectForKey:@"Article"];
        NSEntityDescription *tagEntity = [[model entitiesByName] objectForKey:@"Tag"];
        [RKSearchIndexer addSearchIndexingToEntity:articleEntity onAttributes:@[ @"title", @"body" ]];
        [RKSearchIndexer addSearchIndexingToEntity:tagEntity onAttributes:@[ @"name" ]];
    } else if ([[model versionIdentifiers] containsObject:@"3.0"] || [[model versionIdentifiers] containsObject:@"4.0"]) {
        // We index the same attributes on v3 and v4
        NSEntityDescription *articleEntity = [[model entitiesByName] objectForKey:@"Article"];
        NSEntityDescription *tagEntity = [[model entitiesByName] objectForKey:@"Tag"];
        [RKSearchIndexer addSearchIndexingToEntity:articleEntity onAttributes:@[ @"title", @"body", @"authorName" ]];
        [RKSearchIndexer addSearchIndexingToEntity:tagEntity onAttributes:@[ @"name" ]];
    }
 }];

Warning: This method is only usable with a versioned Managed Object Model stored as a .momd package containing .mom managed object model archives.

Declared In

RKManagedObjectStore.h

setDefaultStore:

Sets the default managed object store for the application.

+ (void)setDefaultStore:(RKManagedObjectStore *)managedObjectStore

Parameters

managedObjectStore

The new default managed object store.

Declared In

RKManagedObjectStore.h

Instance Methods

addInMemoryPersistentStore:

Adds a new in memory persistent store to the persistent store coordinator of the receiver.

- (NSPersistentStore *)addInMemoryPersistentStore:(NSError **)error

Parameters

error

On input, a pointer to an error object. If an error occurs, this pointer is set to an actual error object containing the error information. You may specify nil for this parameter if you do not want the error information.

Return Value

The new persistent store, or nil in the event of an error.

Discussion

This method will invoke createPersistentStore if a persistent store coordinator has not yet been created.

Declared In

RKManagedObjectStore.h

addSQLitePersistentStoreAtPath:fromSeedDatabaseAtPath:withConfiguration:options:error:

Adds a new SQLite persistent store, optionally initialized with a seed database, to the persistent store coordinator of the receiver.

- (NSPersistentStore *)addSQLitePersistentStoreAtPath:(NSString *)storePath fromSeedDatabaseAtPath:(NSString *)seedPath withConfiguration:(NSString *)nilOrConfigurationName options:(NSDictionary *)nilOrOptions error:(NSError **)error

Parameters

storePath

The path at which to save the persistent store on disk.

seedPath

An optional path to a seed database to copy to the given storePath in the event that a store does not yet exist.

nilOrConfigurationName

An optional name of a Core Data configuration in the managed object model.

nilOrOptions

An optional dictionary of options with which to configure the persistent store. If nil, a dictionary of options enabling NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption will be used.

error

On input, a pointer to an error object. If an error occurs, this pointer is set to an actual error object containing the error information. You may specify nil for this parameter if you do not want the error information.

Discussion

Bug: Note that when built for iOS, this method will set a resource value on the SQLite file backing the persistent store for the NSURLIsExcludedFromBackupKey key set to YES to exclude the SQLite file from being backed up by iCloud to conform with the “iOS Data Storage Guidelines”

Warning: If the seed database at the given path was created with an incompatible managed object model an application error may be raised.

Declared In

RKManagedObjectStore.h

addSearchIndexingToEntityForName:onAttributes:

Adds search indexing to the entity for the given name in the receiver’s managed object model.

- (void)addSearchIndexingToEntityForName:(NSString *)entityName onAttributes:(NSArray *)attributes

Parameters

entityName

The name of the entity in the receiver’s managed object model that should be made searchable.

attributes

An array of NSAttributeDescription objects or NSString attribute names specifying the NSStringAttributeType attributes that are to be indexed for searching.

Discussion

Invocation of this method will result in the entity for the given name being updated to include a new to-many relationship with the name searchWords. The receiver’s search indexer will also be instructed to begin monitoring changes to the specified entity’s searchable attributes to maintain the collection of search words. If no search indexer exists, a new

Warning: Must be invoked before adding persistent stores as the managed object model will become immutable once the persistent store coordinator is created.

Declared In

RKManagedObjectStore+RKSearchAdditions.h

createManagedObjectContexts

Creates the persistent store and main queue managed object contexts for the receiver.

- (void)createManagedObjectContexts

Declared In

RKManagedObjectStore.h

createPersistentStoreCoordinator

Creates a persistent store coordinator with the receiver’s managed object model. After invocation, the persistentStoreCoordinator property will no longer be nil.

- (void)createPersistentStoreCoordinator

Discussion

Warning: Creating the persistent store coordinator will render the managed object model immutable. Attempts to use functionality that requires a mutable managed object model after the persistent store coordinator has been created will raise an application error.

Declared In

RKManagedObjectStore.h

init

Initializes the receiver with a managed object model obtained by merging the models from all of the application’s non-framework bundles.

- (id)init

Discussion

Warning: Obtaining a managed object model by merging all bundles may result in an application error if versioned object models are in use.

Declared In

RKManagedObjectStore.h

initWithManagedObjectModel:

Initializes the receiver with a given managed object model. This is the designated initializer for RKManagedObjectStore.

- (id)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel

Parameters

managedObjectModel

The managed object model with which to initialize the receiver.

Return Value

The receiver, initialized with the given managed object model.

Discussion

Bug: Several features require that the managed object model used to initialize the store be mutable so that entities may be changed before the persistent store coordinator is created. Since iOS 5, managed object models initialized via initWithContentsOfURL: return an immutable model. The application developer must send the returned managed object model a mutable copy message to ensure that it is mutable before initializing the managed object store. The recommended approach for initializing a managed object store is as follows:

NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"MyApplication" ofType:@"momd"]];
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

Declared In

RKManagedObjectStore.h

initWithPersistentStoreCoordinator:

Initializes the receiver with an existing persistent store coordinator.

- (id)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)persistentStoreCoordinator

Parameters

persistentStoreCoordinator

The persistent store coordinator with which to initialize the receiver.

Return Value

The receiver, initialized with the managed object model of the given persistent store coordinator and the persistent store coordinator.

Discussion

The managed object model from the persistent store coordinator will be used to initialize the receiver and the given persistent store coordinator will be configured as the persistent store coordinator for the managed object store.

This initialization method provides for easy integration with an existing Core Data stack.

Declared In

RKManagedObjectStore.h

newChildManagedObjectContextWithConcurrencyType:tracksChanges:

Creates a new child managed object context of the persistent store managed object context with a given concurrency type, optionally tracking changes saved to the parent context and merging them on save.

- (NSManagedObjectContext *)newChildManagedObjectContextWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType tracksChanges:(BOOL)tracksChanges

Parameters

concurrencyType

The desired concurrency type for the new context.

tracksChanges

When YES, the new context will observe the persistentStoreManagedObjectContext for save events and merge in any changes via [NSManagedObjectContext mergeChangesFromContextDidSaveNotification:].

Return Value

A newly created managed object context with the given concurrency type whose parent is the persistentStoreManagedObjectContext.

Declared In

RKManagedObjectStore.h

resetPersistentStores:

Resets the persistent stores in the receiver’s persistent store coordinator and recreates them. If a store being reset is backed by a file on disk (such as a SQLite file), the file will be removed prior to recreating the store. If the store was originally created using a seed database, the seed will be recopied to reset the store to its seeded state. If the managed object model uses External Storage for any of its entities, then the external storage directory will be recursively deleted when the store is reset.

- (BOOL)resetPersistentStores:(NSError **)error

Parameters

error

On input, a pointer to an error object. If an error occurs, this pointer is set to an actual error object containing the error information. You may specify nil for this parameter if you do not want the error information.

Return Value

A Boolean value indicating if the reset was successful.

Discussion

Bug: This method will implictly result in the managed object contexts associated with the receiver to be discarded and recreated. Any managed objects or additional child contexts associated with the store will need to be discarded or else exceptions may be raised (i.e. NSObjectInaccessibleException).

Also note that care must be taken to cancel/suspend all mapping operations, reset all managed object contexts, and disconnect all NSFetchedResultController objects that are associated with managed object contexts using the persistent stores of the receiver before attempting a reset. Failure to completely disconnect usage before calling this method is likely to result in a deadlock.

As an alternative to resetting the persistent store, you may wish to consider simply deleting all managed objects out of the managed object context. If your data set is not very large, this can be a performant operation and is significantly easier to implement correctly. An example implementation for truncating all managed objects from the store is provided below:

NSBlockOpertation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSManagedObjectContext *managedObjectContext = [RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext;
    [managedObjectContext performBlockAndWait:^{
        NSError *error = nil;
        for (NSEntityDescription *entity in [RKManagedObjectStore defaultStore].managedObjectModel) {
            NSFetchRequest *fetchRequest = [NSFetchRequest new];
            [fetchRequest setEntity:entity];
            [fetchRequest setIncludesSubentities:NO];
            NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
            if (! objects) RKLogWarning(@"Failed execution of fetch request %@: %@", fetchRequest, error);
            for (NSManagedObject *managedObject in objects) {
                [managedObjectContext deleteObject:managedObjectContext];
            }
        }

        BOOL success = [managedObjectContext save:&error];
        if (!success) RKLogWarning(@"Failed saving managed object context: %@", error);
        }];
}];
[operation setCompletionBlock:^{
    // Do stuff once the truncation is complete
}];
[operation start];

Declared In

RKManagedObjectStore.h

startIndexingPersistentStoreManagedObjectContext

Tells the search indexer to begin observing the persistent store managed object context for changes to searchable entities and updating the search words.

- (void)startIndexingPersistentStoreManagedObjectContext

Discussion

This is a convenience method that is equivalent to the following example code:

RKSearchIndexer *searchIndexer = managedObjectStore.searchIndexer;
[searchIndexer startObservingManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

Declared In

RKManagedObjectStore+RKSearchAdditions.h

stopIndexingPersistentStoreManagedObjectContext

Tells the search indexer to stop observing the persistent store managed object context for changes to searchable entities.

- (void)stopIndexingPersistentStoreManagedObjectContext

Discussion

This is a convenience method that is equivalent to the following example code:

RKSearchIndexer *searchIndexer = managedObjectStore.searchIndexer;
[searchIndexer stopObservingManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

Declared In

RKManagedObjectStore+RKSearchAdditions.h