wandres.dev
SWIFTDATA · persistencia moderna

Migraciones y sincronización con CloudKit

Cómo evoluciona tu esquema sin perder datos, y cómo sincronizar entre dispositivos con CloudKit casi gratis. Los datos que crecen y viajan contigo.

⏱ 12 min

Una app viva cambia: añades campos, renombras, reorganizas. Y los datos de tus usuarios deben sobrevivir a esos cambios. Además, hoy se espera que todo se sincronice entre iPhone, iPad y Mac. SwiftData cubre ambas cosas con relativamente poco esfuerzo.

🎯 Al terminar esta lección sabrás
  • Migraciones ligeras: qué cambia solo.
  • Migraciones personalizadas con esquemas versionados.
  • Sincronizar con CloudKit.
  • Requisitos para que el sync funcione.

Migraciones ligeras

Si añades una propiedad con valor por defecto, o una nueva opcional, SwiftData migra solo el almacén existente sin que hagas nada:

@Model
class Tarea {
    var titulo: String
    var completada = false
    var prioridad: Int = 0     // campo nuevo con default → migración automática
}

Los usuarios que ya tenían datos los conservan; el campo nuevo aparece con su valor por defecto. La mayoría de los cambios cotidianos entran aquí.

Migraciones personalizadas

Para cambios complejos (renombrar, dividir un campo, transformar valores), defines esquemas versionados y un plan de migración:

enum EsquemaV1: VersionedSchema {
    static var versionIdentifier = Schema.Version(1, 0, 0)
    static var models: [any PersistentModel.Type] { [Tarea.self] }
}

enum PlanMigracion: SchemaMigrationPlan {
    static var schemas: [any VersionedSchema.Type] { [EsquemaV1.self, EsquemaV2.self] }
    static var stages: [MigrationStage] {
        [.custom(fromVersion: EsquemaV1.self, toVersion: EsquemaV2.self,
                 willMigrate: nil, didMigrate: { context in
            // transforma los datos aquí
        })]
    }
}
⚠️
El límite de SwiftData: migraciones pesadas

SwiftData maneja bien las migraciones ligeras y muchas personalizadas, pero para transformaciones muy complejas (las llamadas “heavyweight” de Core Data) sus opciones son más limitadas. Si prevés cambios de esquema drásticos y frecuentes, tenlo en cuenta — lo veremos en la próxima lección.

Sincronizar con CloudKit

Para que los datos viajen entre los dispositivos del usuario vía iCloud, SwiftData se integra con CloudKit casi automáticamente. En Xcode: activa la capacidad iCloud → CloudKit y usa un contenedor con configuración de sync. A menudo basta con:

.modelContainer(for: Tarea.self)   // detecta iCloud si está configurado

Y los datos aparecen en el iPad, el Mac y el iPhone del mismo usuario, sin servidor propio.

Sync gratis, pero con reglas

CloudKit sincroniza sin que montes backend, pero impone condiciones al modelo: cada propiedad debe tener valor por defecto o ser opcional (CloudKit no soporta campos obligatorios sin default), no puedes usar restricciones de unicidad, y las relaciones deben ser opcionales. Diseñar el modelo con estas reglas desde el principio te evita rehacerlo después. Si las cumples, obtienes sincronización multi-dispositivo por prácticamente nada — algo que hace años requería semanas de trabajo de servidor.

⚔️ Prepara tus datos para crecer y viajar
  1. Añade una propiedad nueva con valor por defecto a un modelo y comprueba que la app sigue abriendo tus datos (migración ligera).
  2. Revisa que tus modelos tengan defaults u opcionales (requisito de CloudKit).
  3. En un proyecto de prueba, activa la capacidad de iCloud/CloudKit en Xcode.
  4. Lee la documentación de SchemaMigrationPlan para un cambio de esquema mayor.