Versionado de modelos de datos de Core Data en XCode 5

CoreData en nuestras apps

Cuando comenzamos a trabajar en una aplicación para iOS en la que vamos a necesitar persistir una buena cantidad de datos, una de las opciones recomendables es CoreData.

CoreData es un framework de persistencia totalmente distinto a las otras opciones disponibles para persistir datos en iOS, nos va a permitir usar los datos como objetos, olvidándonos de todo lo relacionado con cómo se guardan esos datos o cómo obtenerlos. Simplemente vamos a almacenar objetos con unos determinados datos y luego los recuperaremos de forma sencilla.

Los objetos que almacenamos en Core Data se definen en XCode como entidades, con una serie de atributos, y una serie de relaciones entre ellas, por lo cual, si por ejemplo tenemos una entidad Library, que tiene una relación To-Many con la entidad Book, nos bastará con acceder a la propiedad books de Library para obtener esos libros, ahorrándonos las típicas consultas a bases de datos.

¿Por qué necesitamos que nuestro modelo de datos sea versionable?

Porque todo esto está muy bien, pero también hay que pensar en que es muy posible (de hecho es lo más normal) que en el futuro necesitemos modificar alguna entidad, ya sea añadiéndole nuevos atributos o relaciones con otras entidades, o incluso añadiendo nuevas entidades.

Si no preparamos el modelo de datos para esta situación, en el momento en el que actualicemos nuestra aplicación con el nuevo modelo de datos, al actualizarse el usuario y cargar dicho modelo, la aplicación devolverá un error, no podrá abrirse, y el usuario habrá perdido los datos (y probablemente nosotros hayamos perdido un usuario).

Para poder evitar esta tragedia, XCode nos permite versionar nuestros modelos de datos de Core Data, de forma que cada vez que lo actualicemos, lo que hará será migrar la anterior versión a la nueva automáticamente.

Existen distintos tipos de migraciones y distintas formas de personalizar el proceso, en este caso vamos a usar la más sencilla y automática, la denominada Lightweight Migration.

¿Cómo podemos realizar esto?

En primer lugar tenemos que observar los métodos de Core Data que XCode crea automáticamente por nosotros cuando creamos un proyecto en el que indicamos que vamos a usarlo. Concretamente vamos a fijarnos en el método (NSPersistentStoreCoordinator *)persistentStoreCoordinator

Esté método devuelve el persistent store coordinator, que es el que se va a encargar de realizar las operaciones sobre los datos, y, en caso de que aun no se haya creado lo creará. Al crearlo, le añade la base de datos como tal, de tipo SQLite, y al añadirla se le pueden pasar una serie de opciones; por defecto no le pasa ninguna opción.


if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 
        // In case of error here would be our way of controling it
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort(); 
} ;

Pues bien, ésta llamada al método addPersistentStoreWithType es la que vamos a tener que modificar añadiéndole las opciones necesarias para que nuestro modelo de datos sea versionable.

Estas opciones las vamos a añadir a un diccionario de la siguiente manera, para poder pasarlo como parámetro en la función que hemos comentado antes.


NSDictionary *options = @{ 
        NSMigratePersistentStoresAutomaticallyOption : @YES,
        NSInferMappingModelAutomaticallyOption : @YES
};
 if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
 ...

La primera de las dos opciones es la que indica a Core Data que tiene que intentar migrar el anterior modelo al nuevo que le estamos proporcionando, y la segunda le dice que tiene que crear dicho modelo automáticamente.

Coredata1

Llegados a este punto nuestro modelo de datos ya soporta migración de versiones. Así que vamos a ponerlo en práctica. Continuemos con el ejemplo del principio, en el que teníamos un entidad  Library y otra Book y estaban relacionadas entre ellas:

Aquí podemos ver que Library tiene una relación To-Many con Books y Books una relación To-One con Library.

Bien, después de haber hecho nuestra versión de la aplicación de la biblioteca, y que los usuarios ya tienen datos en sus aplicaciones, supongamos que queremos ampliar la información añadiendo datos sobre los autores. ¿Cómo hacerlo para que la migración se realice correctamente? Tenemos que seguir varios pasos:

En primer lugar seleccionaremos nuestro archivo de Core Data con extensión .xcdatamodelId y pulsaremos el menú superior de XCode Editor y seleccionaremos la opción Add Model Versión.

Una vez hecho esto le damos un nombre a la nueva versión del modelo y al pulsar OK vemos como el archivo .xcdatamodelId ahora tiene subarchivos de tipo .xcdatamodel, estas son nuestras versiones.

En tercer lugar seleccionamos el nuevo modelo de datos y en el menú lateral derecho, seleccionamos el desplegable Model Version y pulsamos sobre el nombre de nuestro nuevo modelo de datos.

Coredata2

Por último, hecho esto ya solo nos queda modificar el modelo de datos y ejecutar esta nueva versión, y los datos se migrarán automáticamente de un modelo de datos a otro sin perder información.

Coredata1

Para más información:

Deja un comentario

¿Necesitas una estimación?

Calcula ahora