views:

295

answers:

1

My situation is similar to this question. I am using lightweight migration with the following code, fairly vanilla from Apple docs and other SO threads. It runs upon app startup when initializing the Core Data stack.

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

NSError *error = nil;

NSString *storeType = nil;
if (USE_SQLITE) { // app configuration
    storeType = NSSQLiteStoreType;
} else {
    storeType = NSBinaryStoreType;
}

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

// the following line sometimes crashes on app startup
if (![persistentStoreCoordinator addPersistentStoreWithType:storeType configuration:nil URL:[self persistentStoreURL] options:options error:&error]) {
    // handle the error
}

For some users, especially with slower devices, I have crashes confirmed by logs at the indicated line.

I understand that a fix is to switch this to manual mapping and migration. What is the recipe to do that? The long way for me would be to go through all Apple docs, but I don't recall there being good examples and tutorials specifically for schema migration.

+1  A: 

There are good examples on how to do a manual migration but the basic steps are:

  • create a mapping model
  • include that mapping model with your project
  • turn off automigration

However, what is the crash? Are you being killed by the OS for taking too long? As a manual migration will not cure that.

What type of backing store are you using? If you are using binary it is possible to blow out memory because a migration will have two copies of the entire database in memory.

update from OP comment

I think I have seen this happen also with SQLite, so maybe there is something more than memory, although that is a valid point. Yes, it is killed by OS for taking too long, especially on 1G devices. I thought that manual migration was also a way to move from "migrate on app startup which has timeout constraints" to something which has no time constraints, and do it maybe on background thread or such. ?

There is no way to do the migration on a background thread because you are changing the source of the data. If your migration is taking too long on start up then the recommended solution is:

  • Let the -applicationDidFinishLaunching: cycle through the run loop complete without ever touching Core Data. This will stop that crash
  • Kick off the migration on the next iteration through the run loop (probably want to present some kind of progress indicator to the user) and complete the migration.

If you are using a binary store you are probably still going to have memory issues, but this will solve your crash on launch. The crash is the OS saying "I think you have locked up". By letting the -applicationDidFinishLaunching: complete you are telling the OS that you have not locked up.

Marcus S. Zarra
I _think_ I have seen this happen also with SQLite, so maybe there is something more than memory, although that is a valid point.Yes, it is killed by OS for taking too long, especially on 1G devices. I thought that manual migration was also a way to move from "migrate on app startup which has timeout constraints" to something which has no time constraints, and do it maybe on background thread or such. ?
Jaanus
"Let the -applicationDidFinishLaunching: cycle through the run loop complete without ever touching Core Data." -- is the operative piece. I guess this is the same for both automatic and manual migration.
Jaanus
Correct, in either case you need to let the initial load of the application finish in a timely manner.
Marcus S. Zarra