2009-06-19 17 views
94

He leído en la documentación sobre la migración automática/ligera para los modelos de datos básicos, pero tengo problemas en la realidad de implementarlo.¿Qué debo hacer para que Core Data migre automáticamente los modelos?

Según tengo entendido, la aplicación debe notar que el modelo que tiene y el modelo que existe en un dispositivo ya no son lo mismo. Si solo ha agregado atributos o relaciones y cambios simples similares, entonces el modelo debe actualizarse automáticamente.

Cualquier puntero - ¿tengo que configurar algo en xCode?

Respuesta

137

He descubierto que esto es bastante simple, una vez que sabes dónde buscar.

En mi AppDelegate I Puesta en marcha Los NSPersistentStoreCoordinator - y hay que añadir algunas opciones para este contarla para manejar auto-migrar:

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

Luego hay que hacer un pequeño truco en Xcode:

  1. Seleccione su archivo xcdatamodel
  2. Seleccione el menú Diseño en la parte superior - a continuación, Modelo de datos - a continuación, seleccione Agregar Modelo Versión
  3. su xcda El archivo tamodel se moverá a un nuevo directorio con el mismo nombre que su archivo xcdatamodel pero con la extensión xcdatamodeld - habrá un segundo archivo en este directorio con un 2 en el nombre. Seleccione el nuevo archivo y luego Diseño-> Modelo de datos-> Establecer versión actual (in Xcode 4 you do this)
  4. Si ya ha realizado los cambios que han hecho que su proyecto sea incompatible, elimine estos cambios del archivo xcdatamodel original. Si aún tiene que hacer los cambios, simplemente edite el archivo 2.xcdatamodel (el que acaba de crear la versión actual).
  5. Ahora cuando instale esta versión en un dispositivo que tenga el modelo anterior, actualizará automáticamente ese modelo al nuevo modelo.

Esto parece genial y tan simple como yo quería, pero creo que debe tener cuidado durante el desarrollo al cambiar un modelo; de lo contrario, tendrá que crear una nueva versión para cada cambio.

Creo que lo que haré es mantener todos los archivos modificados y luego, cuando me prepare para implementar mi actualización, borraré todos los archivos intermedios y solo implementaré los modelos más antiguos y más recientes.


ACTUALIZACIÓN (15/07/2011):

Gracias a @rockstarberlin para señalar la documentación no se actualiza la manzana:

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

actualización: 8/19/2013 mejor enlace:

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

+0

Sugeriría leer el Core Data Migration y Versioning Guid e, disponible en Xcode doc viewer y en developer.apple.com. – Hunter

+1

No encontré la respuesta simplemente presentada, tomó un tiempo para averiguar cómo hacer esto. – Grouchal

+0

NSInferMappingModelAutomaticallyOption funciona bien, pero solo para asignaciones simples, como cambiar el nombre de un atributo. Para algo más complicado (relaciones, eliminación o adición de entidades) necesitará agregar un modelo de mapeo. Si Xcode se queja de que NSInferMappingModelAutomaticallyOption no está declarado, agregue #import al archivo de encabezado delegado de su aplicación. –

13

Esto fue increíblemente útil. La documentación de Apple era, como de costumbre, tristemente incompleta. Recomiendo hacer una compilación limpia, ya que me encontré con un error "No se pueden combinar modelos con dos entidades diferentes xxx" la primera vez que ejecuté después de hacer estos cambios. La construcción limpia lo solucionó.

+0

Una compilación limpia solucionó mis problemas, también. – jrainbow

6

La respuesta de Grouchal es perfecta ... pero si aún tiene la opción "No se pueden fusionar modelos con dos entidades diferentes xxx" incluso después de limpiar la compilación varias veces ... Puede tener problemas con la forma en que se gestiona ManageObjectModel que se está cargando ... tomar por lo vistazo a esto ... que ayudó a corregir el problema ..

core data migration problems

1

Para dar seguimiento a la respuesta de Santthosh, pensé que había puesto el fragmento de código en su lugar aquí. Es necesario crear su managedObjectModel con initWithContentsOfURL: en lugar de mergedModelFromBundles: lo contrario obtendrá el error:

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

Si el archivo de modelo se denomina "Modelo", así es como se crea el managedObjectModel:

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

crédito a this blog post.

3

Además, si se tropezó con esta publicación, como yo lo hice, después de obtener el error "El modelo utilizado para abrir la tienda no es compatible con el utilizado para crear la tienda" y simplemente está depurando con el simulador y el deseo Para reemplazar por completo el antiguo modelo instalado, puede simplemente restablecer la aplicación del simulador o eliminar su aplicación del simulador probablemente también funcione.

No se me ocurrió intentar esto hasta leer las publicaciones aquí, en ese momento me di cuenta de que había instalado la aplicación en el simulador y luego lo modifiqué, causando el error de tiempo de ejecución mencionado anteriormente.

1

que he tenido este problema durante años, y yo intentado todas estas respuestas en vano. Hoy finalmente descubrí lo que estaba haciendo mal. Problema muy simple, pero lo pasé por alto. Al crear una versión más nueva del modelo de datos, si está AGREGANDO columnas, asegúrese de marcarlos como OPCIONALES. Si no lo hace, la migración simple no funcionará porque los nuevos valores de columna no se completarán.

Tan pronto como me aseguré de que mis nuevas columnas tenían marcada "opcional", intenté la migración nuevamente y funcionó.

0

iOS 4.0+

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

I tropezado con este post porque de un diferentes problemas, pero el error era "la configuración del modelo utilizado para abrir la tienda es incompatible con el que se utilizó para crear la tienda. "

Aquí estaba mi problema y la solución a la misma. En mi modelo, estaba usando configuraciones. Algunas de las entidades se almacenaban en un archivo y las otras en un segundo archivo. (Tengo algunos valores predeterminados que pueden necesitar descargarse periódicamente, y sería un dolor increíble fusionarlos en el conjunto). De todos modos, hice una nueva entidad. El programa parecía funcionar bien, pero cada vez que abandonaba, obtenía el error anterior.

La solución fue ver mis configuraciones, darme cuenta de que tenía una entidad que no estaba actualmente en ninguna de las configuraciones y agregarla a una. Corre como un sueño.

Esto no solucionará el problema del OP. Pero tal vez alguna persona frustrada que aterriza aquí a través de Google estará en el barco que estaba en :)

0

Edición menor a @ instrucciones impresionante de Grouchal anteriores para Xcode versión 5:

antigua: 2. Seleccione el menú Diseño en la parte superior - a continuación, modelo de datos - a continuación, seleccione Agregar modelo Versión

Versión 5+: 2. seleccione el menú Editor y, a continuación Añadir la versión de modelo ..., escriba su nombre y la versión basada en el modelo (seleccione su modelo original de la lista)