Una migración es necesaria cuando cambio el modelo de datos (añado atributos, entidades, relaciones, cambio delete rules, etc.) y necesito que los datos existentes se adapten al nuevo esquema.
Versionar el modelo de datos
Para hacer migraciones, se debe versionar cada versión del modelo de datos (.xcdatamodeld):
- En Xcode, seleccionar el modelo → Editor → Add Model Version.
- Escoger un nombre para la nueva versión (ej: ModelV2).
- Hacer los cambios en esa versión.
- Marcar la nueva versión como Current.
Esto mantiene el historial de versiones, y Core Data sabe desde cuál hasta cuál debe migrar.
Tipos de migraciones en Core Data
1. Lightweight Migration (Migración ligera)
Es la más usada. Core Data hace el trabajo por uno si los cambios son simples y compatibles.
Entre los cambios soportados tenemos:
- Añadir un nuevo atributo con valor por defecto.
- Añadir una nueva entidad.
- Cambiar un atributo opcional a obligatorio (si tiene default).
- Añadir una relación.
- Renombrar atributos o entidades (si se usa
renamingIdentifier).
Para activarla, en el setup del NSPersistentContainer (o NSPersistentStoreCoordinator si lo se usa a mano), habilitamos las opciones de migración:
let container = NSPersistentContainer(name: "MyModel")
let description = container.persistentStoreDescriptions.first
// Core Data debe intentar migrar si detecta cambios.
description?.shouldMigrateStoreAutomatically = true
// y debe adivinar el "mapping" entre modelos antiguo y nuevo.
description?.shouldInferMappingModelAutomatically = true
container.loadPersistentStores { storeDescription, error in
if let error = error {
fatalError("Unresolved error \(error)")
}
}
2. Heavyweight Migration (Migración personalizada)
Si se hacen cambios más drásticos como fusionar o dividir entidades, o cambiar tipos de atributos, Core Data ya no puede inferir cómo hacer la migración. En ese caso es necesario:
- Crear un Mapping Model (.xcmappingmodel) en Xcode: → File → File from Template → Mapping Model.
- Seleccionar las versiones de origen y destino del modelo de datos. Xcode generará automáticamente los mapeos que pueda inferir.
- Buscar la opción "Add Entity Mapping"
- En el "inspector de atributos" (que en realidad es el "Mapping Model Inspector), cambiar el nombre del mapeo, elegir las entidades de origen (source) y destino (destination)
- En la sección "Attribute Mappings", agregar un nuevo mapeo: Elegir el atributo de destino en la columna de la izquierda, y luego, agregar en el lado derecho la expresión que lo genera usando
$sourcecomo la referencia a la entidad de origen (e.g.$source.value + 1). - En la sección "Relatioinship Mappings", agregar un nuevo mapeo: Elegir la relación de destino en la columna de la izquierda, y agregar en el lado derecho la expresión que la genera (e.g.
FUNCTION($manager, "destinationInstancesForSourceRelationshipNamed:sourceInstances:" , "notification", $source.notification)). - En caso de necesitar meas control, se puede implementar una política de migración (
NSEntityMigrationPolicy) de forma programática para transformar datos durante la migración. - Para cargar la migración, se activa la migración de modelos, pero se impide que Xcode infiera el mapeo. Si el modelo de mapeo es correo, Xcode ejecuta la migración heavyweight.
let description = NSPersistentStoreDescription(url: storeURL)
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = false
let container = NSPersistentContainer(name: "MyModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { storeDescription, error in
if let error = error {
fatalError("Migration failed: \(error)")
}
}
Top comments (0)