Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining when there are new versions in core data model

Short question:

I want to run a certain code in my app only if my Core Data model has changed (new entities, new properties, etc). How can I determine if the model has changed or not?

Just some pseudo-code:

    if (current_model_version != previous_model_version) {
    //do some code
    } else {
    // do some other code
    }

I'm guessing I might use versionHashes to do this, or isConfiguration:compatibleWithStoreMetadata:, but I'm not certain how.

Some editing for clarity: 'current' as in 'now' and 'previous' as in 'last time app was launched.'

like image 352
kid_x Avatar asked Oct 06 '12 01:10

kid_x


2 Answers

The answer seems to be isConfiguration:compatibleWithStoreMedia:.

I found some useful information here:

http://mipostel.com/index.php/home/70-core-data-migration-standard-migration-part-2

I set it up this way:

- (BOOL)modelChanged
{
    NSError *error;
    NSURL * sourceURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"db.sqlite"];
    NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:sourceURL error:&error];
    BOOL isCompatible = [[self managedObjectModel] isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata];

    return isCompatible;

}

'self' is my shared data store, not that it necessarily has to go there.

deanWombourne points out that what this really does is determine whether or not the data can be automatically migrated, so it's not exactly the solution to the problem I posed. It does serve my needs in this case.

like image 200
kid_x Avatar answered Oct 06 '22 01:10

kid_x


This is replacement code for - (NSPersistentStoreCoordinator *)persistentStoreCoordinator that you get if you tick the Core Data box when setting up a new project in XCode.

It attempts to open the existing sqlite file (using lightweight migration if necessary). If that fails, it deletes and re-creates the store.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

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

    NSError *error = nil;

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

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error])
    {
        NSLog(@"Couldn't open the store. error %@, %@", error, [error userInfo]);

        [self deleteSqliteFilesForStore:self.storeURL];

        if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:options error:&error])
        {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

            // or [NSException raise ...]
        }
        else
        {
            NSLog(@"Store deleted and recreated");

            // TEST DATA RE-INITIALIZATION CODE GOES HERE
        }
    }
    else
    {
        NSLog(@"Existing Store opened successfully");
    }

    return _persistentStoreCoordinator;
}

- (void)deleteSqliteFilesForStore:(NSURL *)storeURL
{
    NSURL *baseURL = [storeURL URLByDeletingPathExtension];

    // Delete the associated files as well as the sqlite file

    for (NSString *pathExtension in @[@"sqlite",@"sqlite-shm",@"sqlite-wal"])
    {
        NSURL *componentURL = [baseURL URLByAppendingPathExtension:pathExtension];

        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[componentURL path]];
        if(fileExists)
        {
            [[NSFileManager defaultManager] removeItemAtPath:[componentURL path] error:nil];
        }
    }
}
like image 44
DavidA Avatar answered Oct 06 '22 00:10

DavidA