Cosa devo fare per consentire a Core Data di migrare automaticamente i modelli?


96

Ho letto la documentazione sulla migrazione automatica / leggera per i modelli Core Data, ma ho problemi a implementarla.

A quanto ho capito, l'applicazione dovrebbe notare che il modello che ha e il modello che esiste già su un dispositivo non sono gli stessi. Se sono stati aggiunti solo attributi o relazioni e modifiche semplici simili, il modello dovrebbe essere aggiornato automaticamente.

Eventuali suggerimenti: devo impostare qualcosa in Xcode?

Risposte:


138

Ora ho scoperto che è abbastanza semplice, una volta che sai dove cercare.

Nel mio AppDelegate ho configurato NSPersistentStoreCoordinator - e devi aggiungere alcune opzioni a questo per dirgli di gestire la migrazione automatica:

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);
}

Quindi devi fare un piccolo trucco in xCode:

  1. Seleziona il tuo file xcdatamodel
  2. Seleziona il menu Design in alto, quindi Modello di dati, quindi scegli Aggiungi versione modello
  3. Il tuo file xcdatamodel verrà quindi spostato in una nuova directory con lo stesso nome del tuo file xcdatamodel ma con l'estensione xcdatamodeld - ci sarà un secondo file in questa directory con un 2 nel nome. Seleziona il nuovo file e poi Design-> Modello di dati-> Imposta versione corrente ( in Xcode 4 lo fai )
  4. Se hai già apportato le modifiche che hanno reso il tuo progetto incompatibile, rimuovi queste modifiche dal file xcdatamodel originale. Se devi ancora apportare le modifiche, modifica semplicemente il file 2.xcdatamodel (quello che hai appena creato nella versione corrente).
  5. Ora, quando installi questa versione su un dispositivo che ha il vecchio modello, aggiornerà automaticamente quel modello al nuovo modello.

Sembra fantastico e semplice come volevo, ma penso che sia necessario prestare attenzione durante lo sviluppo mentre si modifica un modello, altrimenti sarà necessario creare una nuova versione per ogni modifica.

Penso che quello che farò è che manterrò tutti i file modificati e poi, una volta pronto per distribuire il mio aggiornamento, cancellerò tutti i file intermedi e distribuirò solo con i modelli più vecchi e più recenti.


AGGIORNAMENTO (15/07/2011):

Grazie a @ rockstarberlin per aver sottolineato che c'è una documentazione aggiornata su Apple:

Xcode 4: impostazione della versione corrente di un modello a oggetti gestito

Aggiornamento: 19/8/2013 collegamento migliore:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html


Suggerirei di leggere la Core Data Migration and Versioning Guide, disponibile nel visualizzatore di documenti Xcode e su developer.apple.com.
Hunter

1
Non ho trovato la risposta lì dentro semplicemente - ci è voluto un po 'per scoprire come farlo.
Grouchal

NSInferMappingModelAutomaticallyOption funziona bene, ma solo per semplici mappature, come cambiare il nome di un attributo. Per qualsiasi cosa più complicata (relazioni, rimozione o aggiunta di entità) sarà necessario aggiungere un modello di mappatura. Se Xcode si lamenta del fatto che NSInferMappingModelAutomaticallyOption non è dichiarato, aggiungi #import <CoreData / CoreData.h> al file di intestazione del delegato dell'app.
Elise van Looij,

Ho aggiunto alcune entità al mio modello e ho ricevuto il famigerato errore "Il modello utilizzato per aprire il negozio è incompatibile con quello utilizzato per creare il negozio". La tua soluzione l'ha risolto! Grazie mille!
Karsten Silz

1
Vedi la risposta di Santthosh di seguito se ricevi l'errore "Impossibile unire modelli con due entità diverse denominate" dopo aver seguito queste istruzioni.
benvolioT

14

Questo è stato incredibilmente utile. La documentazione di Apple era - come al solito - tristemente incompleta. Consiglio di eseguire una build pulita, poiché ho riscontrato un errore "Impossibile unire modelli con due entità diverse xxx" quando ho eseguito per la prima volta dopo aver apportato queste modifiche. La build pulita lo ha risolto.


Una build pulita ha risolto anche i miei problemi.
jrainbow

6

La risposta di Grouchal è perfetta ... ma se hai ancora "Impossibile unire modelli con due entità diverse xxx" anche dopo aver ripulito la build più volte ... Potresti avere problemi con il caricamento di managedObjectModel .. .dai un'occhiata a questo ... che mi ha aiutato a risolverlo ..

problemi fondamentali di migrazione dei dati


3

Inoltre, se ti sei imbattuto in questo post, come ho fatto io, dopo aver ricevuto l'errore "Il modello utilizzato per aprire il negozio è incompatibile con quello utilizzato per creare il negozio" e stai facendo il debug utilizzando il simulatore e vuoi sostituire completamente il vecchio modello installato, puoi semplicemente ripristinare l'app Simulator o eliminare l'app dal simulatore probabilmente funzionerebbe anche.

Non mi è venuto in mente di provarlo fino a quando non ho letto i post qui, a quel punto mi sono reso conto di aver installato l'app nel simulatore e quindi successivamente modificato il modello, causando il suddetto errore di run-time.


1

Per dare seguito alla risposta di Santthosh, ho pensato di pubblicare lo snippet di codice proprio qui. Devi creare il tuo managedObjectModel con initWithContentsOfURL:invece di mergedModelFromBundles:altrimenti otterrai un errore:

Non è possibile unire modelli con due entità diverse XXX e XXX

Se il tuo file Model si chiama "Model", ecco come creare il managedObjectModel:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

Ringraziamo questo post del blog .



1

Ho avuto questo problema per anni e ho provato tutte queste risposte senza alcun risultato. Oggi ho finalmente capito cosa stavo facendo di sbagliato. Problema molto semplice, ma l'ho trascurato. Quando si crea una versione più recente del modello di dati, se si stanno AGGIUNGENDO colonne, assicurarsi di contrassegnarle come FACOLTATIVE. In caso contrario, la migrazione semplice non funzionerà perché i nuovi valori di colonna non verranno inseriti.

Non appena mi sono assicurato che le mie nuove colonne fossero "facoltative", ho provato di nuovo la migrazione e ha funzionato.


1

Mi sono imbattuto in questo post a causa di diversi problemi, ma l'errore è stato " La configurazione del modello utilizzata per aprire il negozio è incompatibile con quella utilizzata per creare il negozio. "

Ecco il mio problema e la soluzione. Nel mio modello, stavo usando le configurazioni . Alcune delle entità venivano memorizzate in un file e le altre in un secondo file. (Ho alcune impostazioni predefinite che potrebbero dover essere scaricate periodicamente e sarebbe un dolore incredibile unirle nel tutto). Comunque, ho creato una nuova entità. Il programma sembrava funzionare bene, ma ogni volta che uscivo, ricevevo l'errore precedente.

La soluzione era guardare le mie configurazioni, rendermi conto che avevo un'entità che non era attualmente in nessuna delle configurazioni e aggiungerla a una. Funziona come un sogno.

Questo non risolverà il problema dell'OP. Ma forse qualche persona frustrata che atterra qui tramite google sarà sulla barca in cui ero :)


0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

0

Modifica minore alle fantastiche istruzioni di @ Grouchal sopra per Xcode versione 5:

Precedente: 2. Seleziona il menu Design in alto, quindi Data Model, quindi scegli Add Model Version

Versione 5+: 2. Selezionare il menu Editor, quindi Aggiungi versione modello ..., digitare il nome della versione e in base al modello (selezionare il modello originale dall'elenco)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.