Core Data - Migration question?
Asked Answered
Q

4

5

I am trying to do a migration

I have 2 versions of model

1.xcdatamodel
2.xcdatamodel

I created a mapping model from version 1 to 2

1to2.xcmappingmodel

The problem is that it can't find the migration model that I created so mappingModel always gets nil. Is there anything I have to do to specify what mappingModel it ahould use?

target = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]];
//target and source are initialized correctly
mappingModel = [NSMappingModel mappingModelFromBundles:nil forSourceModel:source destinationModel:target];
Quintie answered 13/4, 2011 at 23:31 Comment(0)
D
4

If you've already created a mapping model from 1.xcdatamodel to 2.xcdatamodel, and properly configured it, then you should be able to do something like this: [Note: the key is specifying NSMigratePersistentStoresAutomaticallyOption]

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
    if (persistentStoreCoordinator)
        return persistentStoreCoordinator;

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyStore.sqlite"]];

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

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

   if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                        configuration:nil
                                        URL:storeUrl
                                        options:options
                                        error:&error])
        {
        // Handle error
        NSLog(@"Error adding persistent store...%@", error);
        // Handle the error. 
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0)
            {
            for(NSError* detailedError in detailedErrors)
                {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
                }
            }
        else
            {
            NSLog(@"  %@", [error userInfo]);
            }

        }
    else
        {
        DLog(@"Persistent store added without incident, apparently.");
        }

    return persistentStoreCoordinator;
    }
Dekow answered 14/4, 2011 at 6:4 Comment(1)
Very interesting I'll try it tomorrow and I'll comment back, thanksQuintie
P
5

It might be that you changed one of your models after creating the mapping model.

Even if a change does not seem relevant it will change the hash value of the model which is used for finding the appropriate mapping model. At least I've been bitten by this just now :-)

Paramilitary answered 9/12, 2011 at 16:15 Comment(2)
This bit me. I added a new field to the destination model (after creating the mapping model) and the whole migration process died. Going back into the model and changing the 'destination' model to same as source, then back again rejigged the hashes and migration was a go after thatExergue
This should be the accepted answer. It answers what the question what asked for.Hebraist
D
4

If you've already created a mapping model from 1.xcdatamodel to 2.xcdatamodel, and properly configured it, then you should be able to do something like this: [Note: the key is specifying NSMigratePersistentStoresAutomaticallyOption]

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
    if (persistentStoreCoordinator)
        return persistentStoreCoordinator;

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyStore.sqlite"]];

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

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

   if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                        configuration:nil
                                        URL:storeUrl
                                        options:options
                                        error:&error])
        {
        // Handle error
        NSLog(@"Error adding persistent store...%@", error);
        // Handle the error. 
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0)
            {
            for(NSError* detailedError in detailedErrors)
                {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
                }
            }
        else
            {
            NSLog(@"  %@", [error userInfo]);
            }

        }
    else
        {
        DLog(@"Persistent store added without incident, apparently.");
        }

    return persistentStoreCoordinator;
    }
Dekow answered 14/4, 2011 at 6:4 Comment(1)
Very interesting I'll try it tomorrow and I'll comment back, thanksQuintie
P
0

To answer the original question, your code looks alright but I'm not why you passed nil as the bundles parameter. The documentation doesn't say one can. So:

NSArray *theBundles = [NSArray arrayWithObject:[NSBundle mainBundle]];
    mappingModel = [NSMappingModel mappingModelFromBundles:theBundles
                                            forSourceModel:source 
                                          destinationModel:target];
Professor answered 6/5, 2011 at 19:7 Comment(2)
Actually the documentation does say that you can pass nil: developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/….Parathyroid
Tempus fugit. It does these days, yes.Professor
C
0

If you pass nil as bundle parameter, it will take [NSBundle mainBundle].

[To response to question of Elise van Looij]

Cubby answered 20/12, 2012 at 16:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.