Crear modelos

Crear un modelo de datos

Normalmente se crean con el editor de Xcode, aunque podrían crearse por código, usando el API correspondiente.

Entidades

Las entidades comparten ciertas características con las clases de la POO y otras con las tablas de una base de datos. Por ejemplo pueden ser abstractas y por tanto no directamente instanciables, como las clases de cualquier lenguaje OO. Por otro lado tienen relaciones con otras entidades (uno-a-uno, uno-a-muchos,...) y por ejemplo se puede especificar qué hacer cuando uno de los "lados" de la relación se elimina, como es típico de las bases de datos relacionales.

Si seleccionamos una entidad podemos ver sus características en el "Data Model Inspector", (Cmd+Alt+3 o clic en el tercer icono del panel de la derecha de la pantalla)

  • Class: por defecto las entidades son de la clase NSManagedObject, pero como ya hemos visto esto nos obliga a usar KVC para acceder a las propiedades, lo que es un poco tedioso. Es más flexible usar nuestras propias clases, como veremos luego.

  • Abstract entity es análogo a las clases abstractas en POO, indica que la entidad no es directamente instanciable y se usa solo para que otras hereden de ella.

  • Con Parent entity podemos especificar si queremos que la entidad herede de otra.

Propiedades

La característica más destacada de una propiedad es el tipo de datos. Podemos elegir de entre una serie de tipos, que pueden verse en la siguiente imagen del editor.

La mayoría son bastante autoexplicativos, salvo los dos últimos. El tipo binario se usa típicamente para imágenes, audio, .... En cuanto a transformable nos permite almacenar cualquier clase Swift/Obj-C. Se parece al binario en el sentido de que en el fondo, los datos se van a almacenar también en binario, pero con transformable proporcionamos un medio de hacer la conversión y a partir de ahí nos "olvidamos" de que el dato se está convirtiendo, si trabajamos con clases propias solo veremos el tipo original.

Cualquier clase (propia o del sistema) que sea conforme al protocolo NSCoding puede usarse como Transformable e iOS se encargará automáticamente de convertirla a/desde NSData. Ya vimos en las primeras sesiones cómo hacer esto, dentro del apartado de “serialización de clases propias” o archiving. Si la clase no es conforme a NSCoding tendremos que crear una clase propia que herede de NSValueTransformer y se encargue de hacer la transformación a/desde NSData.

Además del tipo, las propiedades tienen muchas otras características. Podemos verlas en el "Data Model Inspector", haciendo clic sobre el atributo y luego con el atajo (Cmd+Alt+3) o con clic en el tercer icono del panel de la derecha de la pantalla.

Veamos algunas de ellas:

  • Transient significa que no queremos que la propiedad sea persistente. Es típico de los valores que son calculados a partir de otros y que podemos volver a calcular fácilmente (por ejemplo el total de un pedido). Aun no siendo persistentes, estas propiedades también pueden participar en operaciones de “deshacer y rehacer” (undo & redo)

  • Optional es el contrario del típico "not null" de las bases de datos. Si un campo es opcional, puede ser nil.

  • Indexed también es el mismo concepto que en BD. Un atributo indexado estará optimizado para las búsquedas que hagamos sobre él pero ocupará más espacio de almacenamiento.

  • Reglas de validación: valor mínimo y máximo (si es numérico), longitud mínima y máxima (si es cadena), Reg Exp, la expresión regular con la que deben encajar los valores del atributo.

  • Valor por defecto (default) que se asignará automáticamente si no le damos un valor explícito.

Fetch requests

En el editor podemos crear fetch requests, que son una especie de "consultas predefinidas". Mantenemos pulsado el botón de Add Entity para que aparezca un menú contextual y en él elegimos la opción Add fetch request. Podemos añadir gráficamente las condiciones deseadas. Veremos la sintaxis de las condiciones cuando tratemos las consultas en Core Data.

Relaciones

Las relaciones en Core Data son muy similares al concepto equivalente en BD relacionales: vinculan una entidad con otra u otras, generalmente de otro tipo.

Cuando creamos una relación usando el estilo de “tabla” en el editor visual, las tres características directamente editables son:

  • Nombre: es arbitrario y la única condición es que debe comenzar por minúscula, al igual que las propiedades. No obstante, una práctica común es ponerle el mismo nombre que la entidad a la que vincula pero en minúscula. Por ejemplo si tenemos un Mensaje y queremos establecer una relación con el Usuario que lo ha enviado llamaríamos a la relación simplemente usuario. Si es una relación uno a muchos se suele usar el plural. Así, si tenemos un `Usuario y queremos vincularlo con todos sus mensajes llamaríamos mensajes a la relación.

  • Destino: la entidad vinculada

  • Inversa: Se recomienda que todo vínculo entre entidades tenga su relación inversa, que es la que nos permite "volver al punto de partida". En el ejemplo de mensajes/usuarios, la inversa de la relación usuario sería mensajes.

Las relaciones que no tienen inversa generan warnings en Xcode, ya que Core Data usa la bidireccionalidad para poder mantener la consistencia del grafo de objetos cuando se eliminan entidades.

Al igual que con las entidades y las propiedades, podemos cambiar los atributos de una relación seleccionándola y yendo al “Data Model Inspector”, (recuerda, Cmd+Alt+3 o clic en el tercer icono del panel de la derecha de la pantalla).

  • Transient y optional son equivalentes a los atributos del mismo nombre usados en las propiedades.

  • Delete rule es la típica regla a aplicar cuando se borra la entidad “fuente” de la relación: por ejemplo con cascade si se borra la entidad, las relacionadas también lo hacen automáticamente, con deny no se puede borrar la entidad si hay relacionadas, con nullify la relación inversa se pone a nil y con no action la relación inversa queda tal cual (aunque apuntará a un objeto que ya no existe (!))

  • con Type podemos indicar si es una relación uno a uno o uno a muchos. Las relaciones muchos a muchos las conseguimos poniendo tanto la relación como la inversa con el tipo “a muchos”.

En el editor de data models de Xcode, si nos ponemos en modo Graph podemos ver gráficamente las relaciones entre objetos y crearlas con ctrl-click en la entidad "origen" y arrastrando hasta la entidad destino. Las relaciones "uno a uno" aparecen con una única punta de flecha en el destino, y las "uno a muchos" con dos.

En el caso de relaciones “a muchos” podemos especificar:

  • Si queremos que sean ordenadas (ordered). Por ejemplo nos dará lo mismo el orden para un Género musical que tiene asociados muchos Discos, pero no es indiferente en el caso de una Conversacion y los Mensajes que la componen.

  • La cardinalidad mínima y máxima (podemos fijar un límite numérico o dejarlo vacía (unbounded)

Fetched properties

Son similares a las relaciones, pero no son bidireccionales. Cada fetched property está basada en una consulta (fetch request). Por ejemplo podríamos tener una propiedad mensajes_recientes que nos devolviera los mensajes que ha enviado recientemente un usuario.

Para crear una fetched property mantenemos pulsado el botón de Add attribute hasta que aparezca el menú contextual, donde seleccionamos Add fetched property. Tenemos que especificar su nombre y el predicado (la condición de la “consulta asociada”). Veremos algún ejemplo cuando hablemos de consultas en Core Data.

Cuidado, las fetched properties no son dinámicas, sino lazy, su valor no se recalcula automáticamente cada vez que accedemos a ellas, hay que recalcularlas explícitamente con refreshObject:mergeChanges:.

Last updated