Saltar a contenido

Otros tipos de datos

Hasta el momento hemos visto que en una entidad de Core Data puede haber atributos de diversos tipos: enteros, reales, cadenas, fechas y algún tipo más como URLs, pero es un número de tipos limitado.

¿Y si queremos almacenar un atributo de otro tipo, por ejemplo un array, una imagen o una instancia de cualquier otra clase no contemplada en los casos anteriores?. Si es una clase propia siempre podemos convertirla en otra entidad, pero puede haber casos en los que no tenga mucho sentido complicar el modelo de este modo.

Podemos distinguir dos casos: el caso de datos binarios "puros" como audio, video o imágenes, y el de datos que aunque no son binarios son transformables a binarios (como ya vimos en la primera sesión del módulo, Codables).

Para el primer caso podemos usar directamente el tipo "binary data", en el segundo caso tenemos el tipo transformable, en el que Core Data transformará a binario (NSData) el atributo para hacerlo persistente.

Datos binarios

El tipo de datos "binary data" se suele usar para imágenes, audio, video, etc. Por ejemplo supongamos que tenemos la imagen de perfil del usuario y queremos guardarla en un campo "imagen" que hemos definido como de tipo binary data. Sería tan sencillo como:

//obtenemos el contexto de persistencia
let miDelegate = UIApplication.shared.delegate as! AppDelegate
let miContexto = miDelegate.persistentContainer.viewContext
/creamos el usuario y asignamos algunos campos
let usuario = Usuario(context:miContexto)
usuario.login = "pepe"
//la imagen la tendríamos que sacar de algún lado. Seria un UIImage
let imagen_perfil = ...
///así podemos obtener los datos binarios de una UIImage en PNG 
//hay un método jpgData() que hace lo mismo con JPG
let datos = imagen_perfil.pngData()
//ya lo podemos guardar
usuario.imagen = datos

Para recuperar una UIImage a partir de los datos binarios guardados en Core Data bastaría con llamar al inicializador UIImage(data:) que crea una imagen a partir de datos binarios.

Datos transformables

Con los atributos transformables tenemos dos casos posibles: el "fácil", en el que no tenemos que escribir código ya que Core Data puede realizar la transformación automáticamente, y el más complejo, en el que tendremos que implementar nosotros mismos la transformación. Todo depende de si el dato a almacenar implementa el protocolo NSCoding. Esta es la "versión antigua" del Codable de Swift. Las clases que implementan este protocolo son archivables o serializables. Así que Core Data no hace directamente la transformación sino que recurre a un mecanismo estándar en iOS para archivar/desarchivar objetos.

Por ejemplo supongamos que en una entidad de Core Data quisiéramos almacenar un array de String. No podemos crear un atributo de Core Data de este tipo directamente, pero afortunadamente los arrays implementan el protocolo NSCoding, así que la transformación va a ser automática. Seguiríamos estos pasos

  • En la entidad, definir el tipo del atributo como Transformable.
  • Generar la clase de la entidad con Xcode de manera manual (con Editor>Create NSManagedObject subclass...)
  • Modificar el archivo fuente generado por Xcode, que habrá puesto la propiedad como NSObject y cambiarla por el tipo correspondiente. En este caso [String]. De este modo nos ahorraremos el cast hacia y desde NSObject. La contrapartida es que si volvemos a generar la clase nos tocará volver a editar el archivo.

Ya no hay que hacer nada más. Nosotros trataremos con la propiedad como un array de String y automáticamente se hará la transformación hacia y desde binario, que es como se almacenan los datos.

En caso de que el tipo de datos del atributo no sea conforme al protocolo NSCoding tendremos que escribir una clase propia que haga la transformación a y desde binario. Esto se hace implementando una clase que herede de ValueTransformer, e implementando en ella la lógica de transformación. Para ver un ejemplo concreto podéis consultar por ejemplo este tutorial.