I am currently updating an app to use Core Data. The app you could say is a “database viewer”, only one database is able to be viewed at a time. Each database is kept in its own separate folder. Currently the data is downloaded and stored as a set of plist files.
In the new version I need to convert these plist databases into Core Data stores (one store for each database.) I’ve already setup the methods that create the separate store files, and crete the entities. The problem is that all the entities are saved to the first database I created, not to the “current” or “lastly created” file.
The basic process I’m using is:
//For each database {
//Create the sqlite file and set up NSManagedObjectContext
[MagicalRecord setupCoreDataStackWithStoreNamed:
[NSURL fileURLWithPath:
[NSString stringWithFormat:@"%@/%@/%@.sqlite",
dirPath, directory, directory]]];
NSManagedObjectContext *managedObjectContext =
[NSManagedObjectContext MR_contextForCurrentThread];
//Iterate through all the plist files and create the necessary entities.
//Save new entities to file
[managedObjectContext MR_save];
//Clean up all cashes
[MagicalRecord cleanUp];
}
How would one properly switch between stores, essentially “reseting” everything between each switch. Preferably (if possible) using magical record.
EDIT:
I’ve found out a portion of the problem, and removed most of the unwanted behavior. It turns out, you can’t reliably call [MagicalRecord cleanUp] on a background thread. Also, It isn’t doing what I think it should (see below). I ended up calling back to the main thread after each “save” to reset the Core Data stack. Doing this creates a new context for the first three databases. after that, it duplicates the context from the database three databases ago. So the same three contexts are used in a loop.
This is what I currently have;
I start the process by creating a background thread and run the code to create a single database in the background:
backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
dispatch_async(backgroundQueue, ^(void) {
[self createSQLiteDatabase:updateList];
});
Then creating the stack and database:
- (void)createSQLiteDatabase:(NSArray *)updateList
{
NSString *directory = [updateList objectAtIndex:0];
[MagicalRecord setupCoreDataStackWithStoreNamed:
[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@/%@.sqlite",
dirPath, directory, directory]]];
NSManagedObjectContext *managedObjectContext =
[NSManagedObjectContext MR_contextForCurrentThread];
//Check to see if the stack has reset
NSLog(@"Before:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);
//Create and add entities to context...
//Prepare for next loop
NSLog(@"After:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);
[managedObjectContext MR_saveNestedContexts];
[NSManagedObjectContext MR_resetContextForCurrentThread];
NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:updateList];
[temp removeObjectAtIndex:0];
dispatch_async(dispatch_get_main_queue(), ^(void){
[self shouldContinueUpdating:temp];
});
Then reset everything and repeat for all databases:
- (void)shouldContinueUpdating:(NSArray *)databases
{
//preform cleanup on main thread and release background thread
[MagicalRecord cleanUp];
dispatch_release(backgroundQueue);
if ([databases count] != 0) {
backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
dispatch_async(backgroundQueue, ^(void) {
[self createSQLiteDatabase:databases];
});
}
}
With the two NSLogs, I get this in the console: (using six databases, the pattern is the same no matter how many databases I convert.)
//First Loop
Before:0
After:308
//Second Loop
Before:0
After:257
//Third Loop
Before:0
After:37
//Fourth Loop
Before:308
After:541
//Fifth Loop
Before:257
After:490
//Sixth Loop
Before:37
After:270
... Keep adding to each of the three contexts.
And [MagicalRecord cleanUp] isn’t doing what It say it’s doing. Here is what the method is supposed to do.
+ (void) cleanUpStack;
{
[NSManagedObjectContext MR_cleanUp];
[NSManagedObjectModel MR_setDefaultManagedObjectModel:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:nil];
[NSPersistentStore MR_setDefaultPersistentStore:nil];
}
But It turns out that the NSStoreCoordinator every time I save, is the same coordinator, in the same memory location, and each store is hanging around. Something is not working right…
Turns out The problem I’m having is because of a bug in MagicalRecord. I’ve submitted a git issue here: https://github.com/magicalpanda/MagicalRecord/issues/270