Ahmed Z.
Ahmed Z.

Reputation: 2337

iOS Core Data Migration big Issue

when i started developing the app, I had a Core data model with 5 Entities (named Visitors, UnreadMessages, ContactStatuses, UserVCard and User). The app went live on app store.. no issue in that.. Now i had to add some requirement changes so the core data model changed minorly by having 2 more entities added to it (named AudioSupportedWindows and AudioMessages)

So according to a lot of articles, SO posts, and apple documentation, The way to migrate this was LightWeight migration so for that I added the following code

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

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType        configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

in my persistentStoreCoordinator method. But it always gives a Can't find model for source store error.

After that I started of with manual migration using a migration mapping according to this link Core Data - Default Migration ( Manual )

But when i run this I get both source and destination models but they are identical that is they both consisting on 5 entities. and i get this error The model used to open the store is incompatible with the one used to create the store

terribly em in deep trouble ryt now solving this… any help would be greatly appreciated.

Edit 1

- (NSManagedObjectModel *)managedObjectModel
{
    if (managedObjectModel != nil)
    {
        return managedObjectModel;
    }
    
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"UserData" withExtension:@"momd"];
    managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return managedObjectModel;
}

Upvotes: 3

Views: 281

Answers (4)

Ahmed Z.
Ahmed Z.

Reputation: 2337

Thank you everyone for the help… I solved it using lightweight migration.. what i did was delete my xcdatamodeld, recreate it from the one on App Store, make new database file, add new model version.. Somehow i have no clue how it got working…

but em happy it works :)

Upvotes: 0

graver
graver

Reputation: 15213

This might be an issue I've run a few times. Download your app from the app store and run it so it creates the managed object store. Then in your xcode before instantiating your persistent store coordinator try the following:

// Model.momd/Model is the path of the previous model. Make sure it's correct
NSURL *oldUrl = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"Model.momd/Model"] withExtension:@"mom"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:oldUrl];
NSLog(@"Old model version hashes: %@", model.entityVersionHashesByName);

// Change model with your model name
NSURL *currentModelUrl = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"Model"] withExtension:@"momd"];
NSManagedObjectModel *currentModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:currentModelUrl];
NSLog(@"Current model version hashes: %@", currentModel.entityVersionHashesByName);



// storeUrl is the path to the persistent store, created by the app store version
NSDictionary *metadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeUrl error:nil];
NSLog(@"Store metadata: %@", metadata);

Metadata entity hashes should be identical to your old model version hashes. If they are not, then the original model you have and the one you've shipped with are different. You might need to find your old model in your source control repo (hope you have one), otherwise you can try changing those values by hand.

Upvotes: 1

tomi44g
tomi44g

Reputation: 3426

Looks like your model you think you have released is different from the one you actually did. To check what did you submit to iTC:

  • go to Organizer/Archives find the archive you submitted then 'Show in Finder'
  • find the model version file: VersionInfo.plist
  • open the plist have a look into the the hash value for each entity

Comparing the hash value with hash values of your current model (just create a fresh archive) you should be able to find the one which has changed.

Upvotes: 1

Wil Shipley
Wil Shipley

Reputation: 9553

Make sure the original model and the new model are both included in your app, in a model bundle. You can’t just include the new model and expect it to migrate (although that would be cooler), it’s not the way it works.

Your new model should be marked as the “current model.” Your old one is so the old file can still be read. If there are no required new fields in the new model that weren’t in the old one, the lightweight translation should work.

Upvotes: 1

Related Questions