I have a Core Data application which I plan to update with a new schema. The lightweight migration seems to work, but it takes time proportional to the amount of data in the dat
Here is an outline of an approach similar to what ohhorob describes. The difference is that I just display an animated "Upgrading..." HUD rather than a more informative progress bar.
The key point is that nothing tries to access Core Data until the migration has had a chance to do its thing. Therefore, I move all the remaining launch code (including the setting of the rootViewController) that could potentially touch Core Data into a separate method. I then call this method after the migration has completed, or immediately if no migration is required. That looks like this:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
if ([MyManagedObject doesRequireMigration]) { // -doesRequireMigration is a method in my RHManagedObject Core Data framework
[SVProgressHUD showWithStatus:NSLocalizedString(@"Upgrading...", nil) maskType:SVProgressHUDMaskTypeGradient];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// do your migration here
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:NSLocalizedString(@"Success!",nil)];
[self postApplication:application didFinishLaunchingWithOptions:launchOptions];
});
});
} else {
[self postApplication:application didFinishLaunchingWithOptions:launchOptions];
}
return YES;
}
-(void)postApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window.rootViewController = ....
// anything else you want to run at launch
}
This approach should play nice with the watchdog that monitors startup times since the migration will take place off the main thread.