2009-06-19 10 views
94

Ho letto nella documentazione sulla migrazione automatica/leggera per i modelli Core Data, ma sto avendo problemi nella realtà di implementarlo.Cosa devo fare per fare in modo che Core Data esegua la migrazione automatica dei modelli?

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

Tutti gli indicatori - ho bisogno di impostare qualcosa in Xcode?

risposta

137

Ora ho scoperto che questo è abbastanza semplice - una volta che si sa dove guardare.

Nel mio AppDelegate I set-up della NSPersistentStoreCoordinator - ed è necessario aggiungere alcune opzioni a questo per dire che per gestire l'auto-migrazione:

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

allora avete bisogno di fare un piccolo trucco in Xcode:

  1. selezionare il file xcdatamodel
  2. Selezionare il Menu design in alto - allora Data Model - quindi scegliere Aggiungi Modello Versione
  3. tuo xcda il file tamodel verrà quindi spostato in una nuova directory con lo stesso nome del 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 quindi Progetta-> Modello dati-> Imposta la versione corrente (in Xcode 4 you do this)
  4. Se hai già apportato le modifiche che hanno causato la incompatibilità del tuo progetto, prendi queste modifiche fuori dal file originale xcdatamodel. Se non hai ancora apportato le modifiche, modifica il file 2.xcdatamodel (quello che hai appena creato).
  5. Ora quando si installa questa versione su un dispositivo che ha il vecchio modello, aggiornerà automaticamente tale modello sul nuovo modello.

Questo sembra grande e semplice come avrei voluto - ma penso che è necessario fare attenzione durante lo sviluppo come si cambia un modello - altrimenti si dovrà creare una nuova versione per ogni modifica.

Penso che quello che farò è che manterrà tutti i file modificati e poi, una volta pronto a distribuire il mio aggiornamento, eliminerò tutti i file intermedi e mi limiterò a distribuire con i modelli più vecchi e recenti.


AGGIORNAMENTO (15/07/2011):

Grazie a @rockstarberlin per sottolineare la documentazione sono stati pubblicati aggiornamenti di Apple:

Xcode 4: Setting a Managed Object Model’s Current Version

Aggiornamento: 8/19/2013 link migliore:

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

+0

Suggerirei di leggere la migrazione dei dati di base e la guida al controllo delle versioni e, disponibile nel visualizzatore doc Xcode e su developer.apple.com. – Hunter

+1

Non ho trovato la risposta in esso esposta semplicemente - ci è voluto un po 'per scoprire come farlo. – Grouchal

+0

NSInferMappingModelAutomaticallyOption funziona bene, ma solo per mappature semplici, come la modifica del nome di un attributo. Per qualcosa di più complicato (relazioni, rimozione o aggiunta di entità) sarà necessario aggiungere un modello di mappatura. Se Xcode si lamenta che NSInferMappingModelAutomaticallyOption non è dichiarato, aggiungi #import al file di intestazione del delegato dell'app. –

13

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

+0

Una build pulita ha risolto anche i miei problemi. – jrainbow

6

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

core data migration problems

1

dare seguito alla risposta di Santthosh, pensato che avrei posto il frammento di codice proprio qui, invece. È necessario creare il managedObjectModel con initWithContentsOfURL: invece di mergedModelFromBundles: altrimenti si otterrà errore:

Can't merge models with two different entities XXX and XXX

Se il file modello è denominato "Modello", ecco come si crea il managedObjectModel:

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

credito a this blog post.

3

Inoltre, se si è imbattuti in questo post, come ho fatto io, dopo aver ottenuto il messaggio "Il modello utilizzato per aprire il negozio è incompatibile con quello utilizzato per creare il negozio" e si sta eseguendo il debug utilizzando il simulatore e volendo per sostituire completamente il vecchio modello installato, è sufficiente ripristinare l'app del simulatore o eliminare la tua app dal simulatore potrebbe funzionare altrettanto bene.

Non mi è venuto in mente di provare questo fino a leggere i post qui, a quel punto mi sono reso conto che avevo installato l'app nel simulatore e successivamente modificato il modello, provocando l'errore di runtime sopra menzionato.

1

Ho avuto questo problema per anni, e ho provato tutte queste risposte senza alcun risultato. Oggi ho finalmente capito cosa stavo facendo male. Un problema molto semplice, ma l'ho trascurato. Quando si crea una versione più recente del modello dati, se si aggiungono colonne, assicurarsi di contrassegnarle come OPZIONALI. Se non lo fai, la semplice migrazione non funzionerà perché i nuovi valori della colonna non verranno compilati.

Non appena ho verificato che le mie nuove colonne abbiano selezionato "facoltativo", ho provato di nuovo la migrazione e ha funzionato.

0

iOS 4.0+

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

mi sono imbattuto su questo post a causa di un diverso problema, ma l'errore è stato "La configurazione del modello utilizzato per aprire il negozio è incompatibile con quello che è stato utilizzato per creare il "

Ecco il mio problema e la soluzione. Nel mio modello, stavo usando le configurazioni . Avevo alcune delle entità memorizzate in un file e le altre in un secondo file. (Ho alcune impostazioni predefinite che potrebbero essere scaricate periodicamente, e sarebbe un dolore incredibile fonderle nel loro insieme). Ad ogni modo, ho creato una nuova entità. Il programma sembrava funzionare bene, ma ogni volta che ho smesso, ho ricevuto l'errore di cui sopra.

La soluzione era quella di guardare le mie configurazioni, rendersi conto che avevo un'entità che non era correntemente in nessuna delle configurazioni, e aggiungerla a una. Corre come un sogno.

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

0

Modifica minima a @ istruzioni impressionante di Grouchal sopra per Xcode versione 5:

Vecchio: 2. Selezionare il Menu Design in alto - quindi Modello dati - quindi selezionare Aggiungi modello Versione

Versione 5+: 2. Selezionare il menu Editor, quindi Aggiungi modello versione ..., digitare il proprio nome versione e Basato sul modello (selezionare il modello originale dal lista)

Problemi correlati