2012-10-06 58 views
5

Breve pregunta:determinar cuándo hay nuevas versiones de modelo de datos central

Quiero correr un cierto código en mi aplicación sólo si mi modelo Core Data ha cambiado (nuevas entidades, nuevas propiedades, etc). ¿Cómo puedo determinar si el modelo ha cambiado o no?

Sólo algunos pseudo-código:

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

supongo que podría utilizar versionHashes hacer esto, o isConfiguration: compatibleWithStoreMetadata :, pero no estoy seguro de cómo.

Algunas ediciones para mayor claridad: 'actual' como en 'ahora' y 'anterior' como en 'la última vez que se lanzó la aplicación'.

+1

Tal vez la guía [Core Modelo de datos de versiones y migración de datos] (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/Introduction.html) ayuda. – Rob

+0

Sí, estaba cavando a través de eso. isConfiguration: compatibleWithStoreMetadata: lo resolví por mí, pero en cierto modo necesitaba un ejemplo de implementación para comprender exactamente cómo se usaba. –

+0

'isConfiguration: compatibleWithStoreMetadata:' no le dirá que hay una nueva versión; solo le dirá que hay una versión _incompatible_. Si su nueva versión se puede migrar automáticamente, esto devolverá 'SÍ'. _Estoy solo un 90% seguro de esto - ¡tendrás que experimentar para demostrar que estoy bien/mal! _ – deanWombourne

Respuesta

8

La respuesta parece ser isConfiguration: compatibleWithStoreMedia:.

he encontrado alguna información útil aquí:

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

lo configuro esta manera:

- (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; 

} 

'yo' es mi almacén de datos compartida, no es que necesariamente tiene que ir ahí.

deanWombourne señala que lo que realmente hace es determinar si los datos pueden migrarse automáticamente o no, así que no es exactamente la solución al problema que planteé. Sirve a mis necesidades en este caso.

+1

Hay un error tipográfico allí: no pase sourcePath como el parámetro de configuración a isConfiguration: compatibleWithStoreMetadata: también tenga en cuenta que esto solo devolverá SÍ si el almacén coincide con el modelo de objeto actual, por lo que no puede usar esto para determinar la tienda se puede migrar Tienes que probar la migración y verificar si hay un error. – DavidA

+0

Esto debería devolver el inverso lógico de isCompatible, ¿verdad? Si no es compatible, es porque el modelo ha cambiado, ¿correcto? –

+1

He reemplazado isConfiguration: sourcePath con isConfiguration: nil para que el código funcione. Parece un error tipográfico – sergtk

1

Este es el código de reemplazo para - (NSPersistentStoreCoordinator *)persistentStoreCoordinator que obtiene si marca la casilla Datos Core al configurar un nuevo proyecto en XCode.

Intenta abrir el archivo sqlite existente (utilizando una migración ligera si es necesario). Si eso falla, elimina y vuelve a crear la tienda.

- (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]; 
     } 
    } 
} 
Cuestiones relacionadas