2012-10-06 4 views
5

breve domanda:determinare quando ci sono nuove versioni di modello di dati di base

Voglio correre un certo codice nella mia app solo se il mio modello Core Data è cambiato (nuove entità, nuove proprietà, ecc). Come posso determinare se il modello è cambiato o no?

Solo alcuni pseudo-codice:

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

sto cercando di indovinare che potrei usare versionHashes per fare questo, o isConfiguration: compatibleWithStoreMetadata :, ma io non sono certo come.

Alcune modifiche per chiarezza: 'corrente' come in 'ora' e 'precedente' come in 'l'ultima app è stata lanciata.'

+1

Forse la guida [Core Data modello delle versioni e la migrazione dei dati] (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/Introduction.html) aiuta. – Rob

+0

Sì, stavo scavando attraverso di esso. isConfiguration: compatibleWithStoreMetadata: risolto per me, ma avevo bisogno di un esempio di implementazione per capire esattamente come veniva utilizzato. –

+0

'isConfiguration: compatibleWithStoreMetadata:' non ti dirà che c'è una nuova versione - ti dirà solo che c'è una versione _incompatibile_. Se la tua nuova versione può essere migrata automaticamente, restituirà "SÌ". _Sono sicuro solo al 90% di questo - potresti dover sperimentare per dimostrarmi giusto/sbagliato! _ – deanWombourne

risposta

8

La risposta sembra essere isConfiguration: compatibleWithStoreMedia:.

ho trovato alcune informazioni utili qui:

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

ho impostato in questo modo:

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

} 

'sé' è il mio archivio di dati condivisi, non che deve necessariamente andare Là.

deanWombourne sottolinea che ciò che realmente fa è determinare se i dati possono essere migrati automaticamente, quindi non è esattamente la soluzione al problema che ho posto. Serve ai miei bisogni in questo caso.

+1

C'è un errore di battitura - non passare sourcePath come parametro di configurazione a isConfiguration: compatibleWithStoreMetadata: Si noti che questo restituirà SÌ solo se l'archivio corrisponde al modello di oggetto corrente, quindi non è possibile utilizzarlo per determinare lo store può essere migrato. Devi provare la migrazione e verificare un errore. – DavidA

+0

Questo dovrebbe restituire l'inverso logico di isCompatible, giusto? Se non è compatibile, è perché il modello è cambiato, corretto? –

+1

Ho sostituito isConfiguration: sourcePath con isConfiguration: nil per rendere il codice funzionante. Sembra un errore di battitura – sergtk

1

Questo è il codice di sostituzione per - (NSPersistentStoreCoordinator *)persistentStoreCoordinator ottenuto se si seleziona la casella Dati principali quando si imposta un nuovo progetto in XCode.

Si tenta di aprire il file sqlite esistente (utilizzando la migrazione leggera se necessario). Se fallisce, cancella e ricrea lo 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]; 
     } 
    } 
}