Migraciones de bases de datos en Swift: herramientas y prácticas para iOS/macOS

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Migraciones de bases de datos en Swift (iOS/macOS)



El desarrollo de aplicaciones para iOS y macOS a menudo requiere trabajar con bases de datos locales. A medida que la aplicación evoluciona, la estructura de datos cambia inevitablemente: se añaden nuevos campos, se modifican tipos o se eliminan entidades obsoletas. Sin un mecanismo de migración adecuado, estos cambios pueden provocar la pérdida de datos del usuario o el bloqueo de la aplicación. En este artículo, exploraremos las principales herramientas y enfoques para realizar migraciones de bases de datos en Swift, y proporcionaremos ejemplos prácticos para soluciones populares.



¿Por qué son importantes las migraciones?

Las migraciones de bases de datos garantizan:

  • Preservación de datos — los registros del usuario no se pierden al actualizar el esquema.
  • Compatibilidad hacia atrás — la aplicación sigue funcionando con versiones antiguas de los datos.
  • Flexibilidad de desarrollo — la capacidad de cambiar iterativamente el modelo de datos sin intervención manual.


Herramientas principales para migraciones en Swift



1. Core Data + NSPersistentContainer

El framework integrado de Apple proporciona migraciones automáticas y ligeras. Para cambios complejos, se utiliza el versionado manual del modelo.

// Configuración del contenedor con soporte de migracioneslet container = NSPersistentContainer(name: "MyAppModel")container.persistentStoreDescriptions.first?.shouldMigrateStoreAutomatically = truecontainer.persistentStoreDescriptions.first?.shouldInferMappingModelAutomatically = true

container.loadPersistentStores { description, error in if let error = error { fatalError("Error al cargar el almacén: \\(error)") }}

Para la migración manual, se crean versiones del modelo (.xcdatamodeld) y NSMappingModel:

let sourceModel = NSManagedObjectModel(contentsOf: sourceURL)!let destinationModel = NSManagedObjectModel(contentsOf: destinationURL)!let mappingModel = NSMappingModel(from: [sourceModel, destinationModel], forSourceModel: sourceModel, destinationModel: destinationModel)

let manager = NSMigrationManager(sourceModel: sourceModel, destinationModel: destinationModel)try? manager.migrateStore(from: sourceURL, sourceType: NSSQLiteStoreType, options: nil, with: mappingModel, toDestinationURL: destinationURL, destinationType: NSSQLiteStoreType, destinationOptions: nil)


2. GRDB.swift — controlador SQLite moderno

GRDB.swift ofrece un mecanismo de migración flexible basado en el registro de pasos. Las migraciones se ejecutan de forma secuencial y atómica.

import GRDB

var migrator = DatabaseMigrator()

// Registro de la primera migraciónmigrator.registerMigration("v1_create_users") { db in try db.create(table: "users") { t in t.autoIncrementedPrimaryKey("id") t.column("name", .text).notNull() t.column("email", .text).unique() }}

// Registro de la segunda migración (adición de campo)migrator.registerMigration("v2_add_age") { db in try db.alter(table: "users") { t in t.add(column: "age", .integer).defaults(to: 0) }}

// Aplicación de migraciones al iniciar la aplicaciónlet dbQueue = try DatabaseQueue(path: "/path/to/database.sqlite")try migrator.migrate(dbQueue)

Ventajas de GRDB.swift: consultas tipadas, soporte de transacciones, reversión sencilla de migraciones.



3. Realm Swift (ahora Atlas Device SDK)

Realm maneja automáticamente la mayoría de las migraciones, pero para cambios complejos se requiere una actualización explícita del esquema.

import RealmSwift

let config = Realm.Configuration( schemaVersion: 2, migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 1 { migration.enumerateObjects(ofType: "User") { oldObject, newObject in newObject?["fullName"] = "\\(oldObject!["firstName"] ?? "") \\(oldObject!["lastName"] ?? "")" }

Recommendations