2

I have a data-heavy app and I have implemented all my CoreData migration stuff using the visual mapping models in XCode and NSEntityMigrationPolicy implementations for the cleanup code. As it turns out, the migrations on a real device are really lengthy, sometimes taking up to five minutes to complete.

I really need to give feedback to the user when this is going on, and want to KVO the migrationProgress attribute on the NSMigrationManager. The trick is that addPersistentStoreWithType:configuration:URL:options:error: doesn't let you get a reference to the NSMigrationManager in the event that it deems a migration to be necessary.

I discovered that I could get a reference to the NSMigrationManager by implementing the beginEntityMapping:manager:error: callback on my custom NSEntityMigrationPolicy, starting off the observing in there.

The only issue is that by the time you get to the beginEntityMapping call, progress seems to be up to about 30% (also, this 30% typically represents about half the total time spent inside the call to addPersistentStoreWithType, so it's actually even worse than it seems).

Is anyone else aware of any tricks that can be used to get a reference to the NSMigrationManager a bit earlier in proceedings so that I don't have to miss out on the first third of the opportunity to give feedback to the user about why the app is taking so long to start up?

Thanks in advance for any help!

westsider
  • 4,967
  • 5
  • 36
  • 51
glenc
  • 3,132
  • 2
  • 26
  • 42

2 Answers2

0

You can do it with code like this:

 NSMigrationManager *migrationManager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel
                                                                      destinationModel:destinationModel];

//if it's set to NO, we can't migrate due to too much memory
//if it's set to YES (the default), we get no progress reporting!!
//migrationManager.usesStoreSpecificMigrationManager = NO;

NSError *mappingError;
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:sourceModel
                                                                 destinationModel:destinationModel
                                                                            error:&mappingError];

NSPersistentStore *persistentStore;
NSError *addPersistentStoreError;
if (mappingModel) {

    NSError *migrationError;
    BOOL migrationSuccess = [migrationManager migrateStoreFromURL:sourceStoreURL
                                                             type:NSSQLiteStoreType
                                                          options:nil
                                                 withMappingModel:mappingModel
                                                 toDestinationURL:destinationStoreURL
                                                  destinationType:NSSQLiteStoreType
                                               destinationOptions:nil error:&migrationError];

But take special note of -usesStoreSpecificMigrationManager

If it's YES (which you really want to have a much easier migration), you get no progress updates which is the worst catch-22 ever :(

Paul Bruneau
  • 1,026
  • 1
  • 9
  • 15
0

After a few more weeks of hacking around this problem, wasn't able to find any way to achieve this and just stopped using addPersistentStoreWithType:configuration:URL:options:error: altogether and manually triggered migration as per the documentation.

glenc
  • 3,132
  • 2
  • 26
  • 42
  • 1
    Does it actually work for you with a lightweight migration? I've implemented a "manual" migration with an inferred mapping, effectively a lightweight migration, but the progress is always 0.0. (even after a successful migration) – Błażej Sep 30 '12 at 18:56
  • 1
    Not sure about iOS 6, but yes on iOS 5 and earlier you don't appear to get any feedback about progress with a lightweight migration. It's pretty bad and the best you can do is to kinda fudge it by profiling ahead of time and getting some estimates based on the size of the DB and then simulating the progress. But it wouldn't be real progress, just an estimate, which sucks. – glenc Sep 30 '12 at 22:15
  • 1
    I tested on iOS6 and the "migrationProgress" is always 0.0 when the migration is triggered manually, with NSMigrationManager. Not sure about "-addPersistentStoreWithType:..." but as you pointed out you can't really get a reference to a migration manager in this case. – Błażej Oct 01 '12 at 11:54
  • I just went through this myself. If you set migrationManager.usesStoreSpecificMigrationManager = NO then you will get progress updates, but it results in an unusably memory-intensive migration. So we're all still screwed. Even my lightweight one can take several minutes – Paul Bruneau Jun 04 '15 at 14:27