PROBLEM STATEMENT
When attempting to save a record to a read/write store that is one of two SQLite stores assigned to the same PersistentStoreCoordinator, my iPhone app crashes. One obvious issue when saving a record is the PersistentStoreCoordinator does not know in which Store to save the data (only because I don't know how to make this happen).
First I will provide the big picture to make sure my approach is sound. Then I will supply the implementation details.
BACKGROUND
This is a simplified example representing the key aspects of the actual app I am working on.
Seed Data
User Input Scenario
CURRENT IMPLEMENTATION
Core Data Implementation
Data Storage and Retrieval
Of course, there should be no evidence to the user, when looking at pick lists to make a choice for an attribute, that the choices come from two different Stores.
Persistent Store Coordinator Setup
- (NSPersistentStoreCoordinator*)persistentStoreCoordinator {
if (_persistentStoreCoordinator == nil) {
NSArray *bundles = @[[NSBundle bundleForClass:[self class]]];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:bundles]];
NSError *error;
//--------------------------------------------------
// Set options for the USER DATA Persistent Store.
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
//--------------------------------------------------
// Add the USER DATA Store to the Persistent Store Coordinator.
NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.persistentStorePathForUserData
options:options
error:&error];
//--------------------------------------------------
// Set options for the SEED DATA Persistent Store.
options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSReadOnlyPersistentStoreOption : @YES};
//--------------------------------------------------
// Add the SEED DATA Store to the Persistent Store Coordinator.
persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.persistentStorePathForSeedData
options:options
error:&error];
}
return _persistentStoreCoordinator;
}
IMPORTANT GOALS
Keep in mind the following:
RESEARCH
In this case, Save objects from multiple stores to single persistent store, the two Stores were merged followed by fetching all the records, culling out the duplicates, and saving the context. I'm hoping not to have to merge and then check thousands of records for duplicates. (See Important Goal #2 above.)
In this case, What is an efficient way to Merge two iOS Core Data Persistent Stores?, certain entities are read-only and others are read/write. In my app, all entities in the Seed Data Store are read-only and the same entities in the User Data Store are read/write. So I don't think migration is applicable. (See Important Goal #2 above.)
In Apple's, Core Data Programming Guide under "Persistent Store Coordinator", Figure 4 "Advanced persistence stack" shows a Core Data implementation using two Stores, but again, each Store is configured with separate and distinct objects. In my app, each object appears in each Store.
The solution proposed here, Combining Two SQLite Stores Into One, relative to having two stores without relationships between the objects in the different stores seems relevant, but no details are provided to compare to what I have implemented.
I have gone through the first three chapters of, Core Data (2nd Edition), by Marcus Zarra, but he doesn't get into using two stores that don't require migration. Chapter 3, however, does provide a very clear example of versioning. (It's complexity lead me to Important Goal #1 above.)
This solution, Which persistent store is used by default in core data in iPhone, suggests using multiple configurations of the ManagedObjectModel, but each entity is assigned to one and only one configuration. I'm not sure how, or even if, this solution can be extrapolated to my situation.
Maybe the solution proposed here, NSPersistentStoreCoordinator with two types of persistent stores?, is close to what I need. Unfortunately, only requests are addressed. I don't see a method analogous to NSFetchRequest method, setAffectedStores, in Class NSManagedObjectContext for saves.
Thanks to Ray Wenderlich's referral to Mic Pringle, Mic proposed a Managed Object Model architecture with which I was able to solve the issue while adhering to my goals. The key to the solution is utilizing an abstract entity as a parent entity to user and seed entities.
With this architecture, it is possible to create two Configurations that are assigned to separate stores: 1) UserData - r/w store located in the User's Documents directory.
2) SeedData - r only store located in the App Bundle.
The downside is that record ID's must be maintained for the seed data entities (since relationships are not allowed between Configurations), but the huge upside is that changes or additions can be made to the seed data without affecting the user's entries AND without having to adopt any of the cumbersome solutions discussed in the RESEARCH section of the original post of this question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With