¿Qué tengo que hacer para que Core Data migre modelos automáticamente?

96

He leído la documentación sobre la migración automática / ligera para modelos Core Data, pero tengo problemas para implementarla.

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

Cualquier sugerencia: ¿necesito configurar algo en Xcode?

Grouchal
fuente

Respuestas:

138

Ahora descubrí que esto es bastante simple, una vez que sepa dónde buscar.

En mi AppDelegate configuré NSPersistentStoreCoordinator, y necesita agregar algunas opciones a esto para decirle que maneje la migración automática:

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

Entonces necesitas hacer un pequeño truco en xCode:

  1. Seleccione su archivo xcdatamodel
  2. Seleccione el menú Diseño en la parte superior, luego Modelo de datos, luego elija Agregar versión del modelo
  3. Su archivo xcdatamodel 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 ( en Xcode 4 usted hace esto )
  4. Si ya ha realizado los cambios que han provocado que su proyecto sea incompatible, elimine estos cambios del archivo xcdatamodel original. Si aún no ha realizado los cambios, simplemente edite el archivo 2.xcdatamodel (el que acaba de hacer en la versión actual).
  5. Ahora, cuando instale esta versión en un dispositivo que tiene el modelo anterior, actualizará automáticamente ese modelo al nuevo modelo.

Esto parece genial y tan simple como 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 conservar todos los archivos modificados y luego, una vez que esté listo para implementar mi actualización, eliminaré todos los archivos intermedios y simplemente lo implementaré con los modelos más antiguos y más recientes.


ACTUALIZACIÓN (15/07/2011):

Gracias a @ rockstarberlin por señalar que hay documentación actualizada en Apple:

Xcode 4: configuración de la versión actual de un modelo de objetos administrados

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

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

Grouchal
fuente
Sugeriría leer la Guía de control de versiones y migración de datos básicos, disponible en el visor de documentos de Xcode y en developer.apple.com.
Hunter
1
No encontré la respuesta allí presentada de manera simple, me tomó un tiempo descubrir cómo hacer esto.
Grouchal
NSInferMappingModelAutomaticallyOption funciona bien, pero solo para asignaciones simples, como cambiar el nombre de un atributo. Para cualquier cosa más complicada (relaciones, eliminar o agregar entidades), deberá agregar un modelo de mapeo. Si Xcode se queja de que NSInferMappingModelAutomaticallyOption no está declarado, agregue #import <CoreData / CoreData.h> al archivo de encabezado delegado de su aplicación.
Elise van Looij
Agregué algunas entidades a mi modelo y obtuve el infame error "El modelo usado para abrir la tienda es incompatible con el usado para crear la tienda". ¡Tu solución lo arregló! ¡Muchas gracias!
Karsten Silz
1
Vea la respuesta de Santthosh a continuación si obtiene el error "No se pueden combinar modelos con dos entidades diferentes nombradas" después de seguir estas instrucciones.
benvolioT
14

Esto fue muy útil. La documentación de Apple estaba, como de costumbre, lamentablemente incompleta. Recomiendo hacer una compilación limpia, ya que encontré el error "No se pueden combinar modelos con dos entidades diferentes xxx" cuando ejecuté por primera vez después de realizar estos cambios. La construcción limpia lo arregló.

Scott Means
fuente
Una construcción limpia solucionó mis problemas también.
jrainbow
6

La respuesta de Grouchal es perfecta ... pero si todavía tiene el mensaje "No se pueden fusionar modelos con dos entidades diferentes xxx" incluso después de limpiar la compilación varias veces ... Es posible que tenga problemas con la forma en que se está cargando el modelo managedObjectModel ... .mire este ... que me ayudó a solucionarlo ...

problemas de migración de datos básicos

Santthosh
fuente
3

Además, si te topaste con esta publicación, como lo hice yo, después de recibir el error "El modelo usado para abrir la tienda es incompatible con el usado para crear la tienda" y solo estás depurando usando el simulador y queriendo reemplazar completamente el modelo anterior instalado, puede simplemente restablecer la aplicación Simulator o eliminar su aplicación del simulador probablemente también funcionará.

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

dreyln
fuente
1

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

No se pueden combinar modelos con dos entidades diferentes XXX y XXX

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

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

Crédito a esta publicación de blog .

samvermette
fuente
1

He tenido este problema durante años y probé todas estas respuestas en vano. Hoy finalmente me di cuenta de lo que estaba haciendo mal. Problema muy simple, pero lo pasé por alto. Al crear una versión más reciente del modelo de datos, si está AGREGANDO columnas, asegúrese de marcarlas 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 tuvieran "opcional" marcado, intenté la migración nuevamente y funcionó.

Cerebro2000
fuente
1

Me encontré con esta publicación debido a un problema diferente, pero el error fue " La configuración del modelo utilizada para abrir la tienda es incompatible con la que se utilizó para crear la tienda. "

Aquí estaba mi problema y la solución. En mi modelo, estaba usando configuraciones . Tenía algunas de las entidades almacenadas en un archivo y las otras en un segundo archivo. (Tengo algunos valores predeterminados que pueden necesitar ser descargados 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 salía, recibía el error anterior.

La solución allí fue mirar 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 aterrice aquí a través de Google estará en el barco en el que estaba :)

El cappy
fuente
0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Stian Høiland
fuente
0

Edición menor de las increíbles instrucciones de @ Grouchal anteriores para la versión 5 de Xcode:

Antiguo: 2. Seleccione el menú Diseño en la parte superior, luego Modelo de datos, luego elija Agregar versión del modelo

Versión 5+: 2. Seleccione el menú Editor, luego Agregar versión de modelo ..., escriba el nombre de su versión y Basado en modelo (seleccione su modelo original de la lista)

PGSeattle
fuente