RKManagedObjectStore Class Reference
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
-
+ defaultStore
Returns the default managed object store for the application.
-
+ setDefaultStore:
Sets the default managed object store for the application.
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
-
managedObjectModel
Returns the managed object model of the receiver.
property -
persistentStoreCoordinator
Returns the persistent store coordinator of the receiver.
property -
managedObjectCache
The managed object cache associated with the receiver.
property
Working with Managed Object Contexts
-
– createManagedObjectContexts
Creates the persistent store and main queue managed object contexts for the receiver.
-
persistentStoreManagedObjectContext
Returns the managed object context of the receiver that is associated with the persistent store coordinator and is responsible for managing persistence.
property -
mainQueueManagedObjectContext
The main queue managed object context of the receiver.
property -
– 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.
Performing Migrations
-
+ migratePersistentStoreOfType:atURL:toModelAtURL:error:configuringModelsWithBlock:
Performs a migration on a persistent store at a given URL to the model at the specified URL.
RKSearchAdditions Methods
-
– addSearchIndexingToEntityForName:onAttributes:
Adds search indexing to the entity for the given name in the receiver’s managed object model.
-
searchIndexer
The search indexer for the receiver’s primary managed object context.
property -
– startIndexingPersistentStoreManagedObjectContext
Tells the search indexer to begin observing the persistent store managed object context for changes to searchable entities and updating the search words.
-
– stopIndexingPersistentStoreManagedObjectContext
Tells the search indexer to stop observing the persistent store managed object context for changes to searchable entities.
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
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 enablingNSMigratePersistentStoresAutomaticallyOption
andNSInferMappingModelAutomaticallyOption
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 orNSString
attribute names specifying theNSStringAttributeType
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 thepersistentStoreManagedObjectContext
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