3
votes

I am using Magical Record in a fairly large IOS project. I use configurations to separate a large seed database from user data. Since Magical Record doesn't support configurations, I deconstructed Magical Record's setupCoreDataStackWithAutoMigratingSqliteStoreNamed method and replaced it with the following:

+(void) RB_setupMultipleStores:(NSString *) seedStoreName userStore:(NSString *) userStoreName
/* change persistent store to one with multiple configurations. Assumes Magical Record is initialized to perform auto migration. */   
{        
NSError * error= nil;

[MagicalRecord cleanUp];  //Tear down Magical Record

NSManagedObjectModel * model = [NSManagedObjectModel MR_defaultManagedObjectModel];

NSURL *seedURL = [NSPersistentStore MR_urlForStoreName:[seedStoreName stringByAppendingString:@".sqlite"]];

NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                         nil];

NSPersistentStore * seedStore =[coordinator
                                            addPersistentStoreWithType:NSSQLiteStoreType
                                                         configuration:@"Seed"
                                                                   URL:seedURL
                                                               options:options
                                                                 error:&error];
if (!seedStore || error)
{
    NSLog(@"Error setting up seed store:%@ for %@", [error localizedDescription], seedURL);
    exit(-1);
}

NSURL *userURL = [NSURL URLForDocumentDirectoryWithAppendedPath:[userStoreName stringByAppendingString:@".sqlite"]];

NSPersistentStore * userStore = [coordinator
                                 addPersistentStoreWithType:NSSQLiteStoreType
                                                          configuration:@"User"
                                                                    URL:userURL
                                                                options:options
                                                                  error:&error];

if (!userStore || error)
{
    NSLog(@"Error setting up user store:%@ for %@", [error localizedDescription], userURL);
    exit (-1);
}
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator];

//Bring back Magical Record with updated coordinator.

[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator];

[[NSManagedObjectContext MR_defaultContext] setUndoManager:nil];
}

Now I will be adding Restkit to the mix. I'd need to share the object model and persistent store, and I'd rather use one set of contexts rather than have two different stacks.

I see five potential approaches:

  1. Modify https://github.com/blakewatters/RKMagicalRecord to support multiple configurations. This looks trivial but it requires I use a category to surface some private methods, and the good MR developers recommend against explicitly setting MR default and root saving contexts.

  2. Create the Magical Record contexts first, and then assign them to Restkit. Will this even work? Does it make sense at all?

  3. Initialize Restkit and Magical Record from the same NSPersistentStoreCoordinator. Does this make sense?

  4. Create two separate stacks with different but similar NSPersistentStoreCoordinators.

  5. Create my own stack and contexts, and make all calls to Restkit and MR using those contexts.

Can anyone recommend any of these or any other approaches? Each requires significant effort to even test. I'm about to head down the #1 path.

Thanks...

1
Hi @ron, could you please update your original code with the solution you mention to have achieved in the accepted answer? Thank you - DAN

1 Answers

4
votes

Fundamentally, CoreData has ways to deal with this already. You can have multiple coordinators point to the same store, or whatever your scenario is. It's up to each framework to allow you to be used against a stack that framework itself did not create or setup.

MagicalRecord boils down to a collection of helper methods for fetching and saving. You don't need to use ANY of the setup methods for MagicalRecord to work its magic on your fetches. The setup methods are there to help you get going faster on new projects, as well as providing a single access point for a "default" contexts for use when you perform fetches on the main thread/queue. For all other use, use the explicit inContext: parameter every time. Using that parameter, you can use whatever MOC you want, everything will work. This is by design. MagicalRecord was never written to replace CoreData. It was written to make the simple tasks easier.

With that, you could just let RestKit deal with your entire CoreData stack and use MagicalRecord only for the convenience APIs for fetching and saving. This would save you having to do any of those solutions and just get back to tackling your app specific issues...