0

When my app attempts to migrate old core data to the new store using standard migration, if the core data store is large then it runs out of memory and crashes.

I've seen it mentioned in several places that the solution is to do it in 'multiple passes', but the apple documentation isn't too great on explaining that:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/vmCustomizing.html#//apple_ref/doc/uid/TP40004399-CH8-SW9

This tutorial here is a lot better, showing the code, but I'm left confused as to where this code goes:

Example or explanation of Core Data Migration with multiple passes?

This is the code I have:

- (NSManagedObjectContext *)managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [NSManagedObjectContext new];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    //managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"EntryDatabase" ofType:@"momd"];
    NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
    managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"CoreDataStore.sqlite"];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    // If the expected store doesn't exist, copy the default store.
    if (![fileManager fileExistsAtPath:storePath]) {

        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"CoreDataStore" ofType:@"sqlite"];
        if (defaultStorePath) {
            NSError *error;
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:&error];
            NSLog(@"Error");
        }
    }

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    NSError *error;
    NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                [NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
                                nil];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:pscOptions error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }    

    return persistentStoreCoordinator;
}

I'm unsure how to implement multiple passes into the code I have - such as where it should go.

Community
  • 1
  • 1
Andrew
  • 15,935
  • 28
  • 121
  • 203
  • It seems like multiple passes only works if your model can be separated into chunks that don't connect to each other. This link looked the most promising: http://stackoverflow.com/a/4915888/1633251 The other way to do it is brute force - you open the old repository, create a new one, the for each entity you copy its attributes to the new entity in one pass, then in a second pass you wire up the relationships. This is obviously a tedious, error prone, and complex task. – David H Sep 13 '12 at 21:44
  • @DavidH Wow, i didn't realise that this wouldn't work if you don't have relationships. It seems like a huge flaw in iOS, that it doesn't have a sensible way to migrate large amounts of data. I feel like I must be missing something. Something that would allow me to simply update my data without it crashing? – Andrew Sep 13 '12 at 21:56
  • Well, you could create a web service, upload the old one, do the conversion on a server, then send the new one back. You should strive for the lightweight solution in the link above. – David H Sep 13 '12 at 22:39

0 Answers0