¡Atención! Este sitio utiliza cookies.
Si no cambias la configuración de tu navegador, aceptas su uso.

Semillas de Cacao: Core Data II – El Modelo

Ya vimos en la anterior entrada en qué consistía CoreData y creamos un pequeño modelo a partir del entorno que nos proporciona la herramienta. Esta vez vamos a definir el modelo de nuestra aplicación, osease, el alma.

Tutorial sobre CoreData en mhjaso.com.

  1. Introducción a CoreData.
  2. El Modelo.
  3. Acceso a datos y guardado.

En este punto deberíamos tener:

  • Un proyecto de Xcode con un archivo .xcdatamodeld
  • Un CoreDataStack (con su .h y su .m)
  • Tres tablas (Character, Scenario y Race) con sus relaciones
  • Y sobre todo muy claro qué es una Entidad, un Atributo y una Relación en términos de CoreData.

Repasa si no lo tienes claro al 100% qué es el ManagedObjectContext (MOC), el ManagedObjectModel (MOM), así como el Persistent StoreCoordinator y el PersistentObject Store. Son especialmente importantes los dos primeros, ya que interactuamos directamente con ellos.

Ahora viene lo nuevo

Antes de seguir, nos hace falta conocer algunos objetos que nos iremos encontrando conforme avancemos. Los veremos aquí todos y así podrás volver a este punto si te surgen dudas.

  • NSManagedObject: Representa cada fila/tupla de una tabla. Será el objeto que utilicemos para representar cada instancia de una Entidad. Por ejemplo, de una tabla Personaje, cada NSManagedObject será una instancia de un personaje.
  • NSManagedObjectContext: Este es muy importante, ya que es la plataforma que ‘sostiene’ todos nuestros NSManagedObject. Representa todo nuestro modelo en memoria. A él le pediremos que haga búsquedas o que guarde los cambios que hayamos hecho en el modelo. Ten en cuenta que hasta que no le demos la orden de guardar no escribirá los datos en disco, sino que los mantendrá en memoria, así que más te vale llevarte bien con él antes de que se cierre la app.
  • NSEntityDescription: Describe una entidad de CoreData.
  • NSManagedObjectModel: Es el mapa de entidades que hemos creado anteriormente en el asistente gráfico. Él tiene la definición de cómo es nuestra base de datos. Normalmente la burocracia nos mantiene alejados de esta clase.
  • NSFetchRequest: En lo que se refiere a búsquedas, este es el p*** amo. Pídele lo que quieras, que irá al contexto a traértelo en un santiamén, de la entidad que quieras y ordenado como te dé la gana. Además, con la ayuda de un NSPredicate, podrás filtrar los resultados como un señor.
  • NSPredicate: Este no es típicamente de CoreData sino que está dentro de Cocoa y sirve para filtrar cualquier tipo de colección con resultados diversos. Aprende a usarlo y lo agradecerás en el futuro.
  • NSPersistentStoreCoordinator: Aunque el Contexto (NSManagedObjectContext) sea quien reciba la orden de guardar los datos en disco, es esta instancia la que  hace realmente el trabajo duro. Ella es quien se relaciona con los contextos (sí, podemos tener varios) y con las bases de datos (sí, has leído bien, también está en plural). En una aplicación sencilla solo usaremos uno, y ni siquiera recordaremos que existe…
Esquema de Core Data

Esquema de Core Data

Técnicamente, podría haber varios NSManagedObject Context y varios Persistent Objects (no aparecen en este esquema pero estaría en contacto directo con la base de datos). Todos se malearían con un solo modelo. En este ejercicio usaremos este esquema más simplificado.

¡Ya basta de tanta teoría, vamos al código que me va a estallar la cabeza!

Está bien, está bien… Vamos a generar nuestras primeras líneas de código, aunque serán automáticas. CoreData requiere de una buena base teórica y realmente de poco código para ejecutarla. Considéralo una ventaja con un coste inicial elevado.

Secuencia de Reanimator

 

Creando nuestros NSManagedObjects… tras una pequeña pausa

No estaría de más que antes de crear NSManagedObjects de nuestro modelo supiéramos el por qué.

Core Data funciona perfectamente mediante el mecanismo KVC (Key Value Coding) que tienen casi todas las clases de Cocoa, y que básicamente consiste en acceder a las propiedades de un objeto haciendo referencia a su nombre (habrás visto un ‘valueForKey’ varias veces en el autocompletado de Xcode), es decir, como si fuera un diccionario. Esto es posible con CoreData y de hecho sería perfectamente factible trabajar así, pero como somos seres civilizados y no nos gusta complicarnos excesivamente, vamos a crearlos archivos de nuestras clases y poder usarlas así desde código como hacemos de normal.

Si te afeitas con un cuchillo y un cubo, este tutorial no es para ti

Si te afeitas con un cuchillo y un cubo, este tutorial no es para ti

Por fin, vamos a generar las clases del modelo.

Vámonos a nuestro modelo de CoreData, el archivo .xcdatamodeld, y seleccionamos todas las entidades del panel izquierdo, como en la imagen (usa CMD o SHIFT para esto).

#1

Ve al Menú -> Editor -> Y Selecciona Create NSManagedObject Subclass.

#2

Te saldrá un asistente como en la imagen, con el nombre de tu modelo. Yo lo llamé Model en un alarde de originalidad literaria, pero tú lo pudiste llamar ‘fistro’ o lo que te diera la gana. Le damos a Siguiente.

#3

Nos pregunta qué entidades queremos generar en código. Si antes marcaste todas las que teníamos, te deberían aparecer todas seleccionadas. Si no lo hiciste ahora puedes hacerlo aquí. Asegúrate de tener todas marcadas y dale a… Siguiente.

#4

Por cierto, ese check sobre generar variables escalares déjalo tranquilo de momento. Simplemente, te permite referirte en código a datos primitivos por su variable escalar (int, float, double, Cheesburguer, etc) en lugar de hacerlo mediante objetos (NSNumber). Haz lo que más te interese en realidad, porque a CoreData en el fondo le da un poco igual. 

Fíjate que en el navegador de proyecto (el panel de la izquierda donde están tus archivos) han aparecido unas cuantas clases como por arte de magia (automágicamente que diría alguno). Eso es tu modelo, recién salido del horno, listas para ser usadas.

#5

Antes de seguir, vamos a meterlas en una carpeta junto al archivo xcdatamodeld antes de que se nos pierdan por ahí. A la carpeta la vamos a llamar Model.

#6

Se ve pero no se toca.

Ahora que ya tienes tu código del modelo… No lo toques. ¿Por qué? Por dos razones:

  • Son clases autogeneradas. Puedes hurgar para conocer cómo es tu modelo, pero no conviene modificar nada de lo que hay  ahí ya que podrías provocar consecuencias inesperadas. Vamos, que lo más probable es que vayas a joder algo, así de claro.
  • Como son clases autogeneradas, ¿qué pasa si vuelves a repetir el proceso? Si metes o alteras código aquí dentro la próxima vez que necesites regenerar estos archivos porque has cambiado algo del modelo, se sobreescribirán. De modo que si no me has hecho caso en el paso anterior y jodes algo, tranquilo porque repitiendo el asistente lo dejarás como CoreData manda.

Llegado este momento, la pregunta que te estarás haciendo ahora (o deberías estar haciéndotela) es: ¿Cómo añado métodos a estas clases? Si no era esa te respondo ya: sí, acepto donativos.

Perpetrando el código…

Ya hemos dicho que estas clases están  muy bien, pero mejor tocarlas con un palo. Bien, pues a crear ese palo. ¿Cómo? Con Categorías. Hay otras formas de hacerlo, como subclasificando o con mogenerator, pero en este tutorial lo haremos de esta manera.

Si no sabes lo que son las categorías, te lo explico brevemente: las Category Classes sirven para añadir métodos a otra clase, la que categorizan. Así que, si tenemos nuestra clase Character y queremos tener la tranquilidad de poder machacarlo tantas veces como hagan falta (que serán unas cuantas, te lo aseguro), creamos una clase Categoría sobre esta última y le añadimos ahí los métodos. Los métodos de una clase Categoría  funcionan como si en realidad estuvieran dentro de la propia clase, pero no lo están, esa es la ventaja. Los métodos que crees estarán siempre a salvo de la hecatombe cuanto toque regenerar las clases del modelo.

Si no has entendido ni papa de esto, lo harás pronto… Te lo garantizo.

Vamos a crear una de prueba. Si en el futuro te hacen falta más, repite el proceso, es sencillo.

Creamos una nueva clase del proyecto desde Archivo -> Nuevo… -> Archivo. Esta vez seleccionamos Category.

#7

La llamamos ‘Methods’, por ejemplo, y la categorizamos sobre la clase ‘Character‘, por ejemplo.

#8

No te afanes demasiado en meterlas todas juntitas dentro de una carpeta y deja la original donde está, no vaya a ser que luego acabes con duplicados (créeme, no quieres eso).

Todo listo. Que empiece la fiesta

Vámonos al AppDelegate.m, y concretamente el método application:didFinishLaunchingWithOptions:

Vamos a seguir proceso habitual: Crear el Modelo, los Controladores y combinadores.

Ahora bien, ‘¿dónde está mi Modelo?’, te preguntarás. Lo tiene CoreData, así que vamos a pedírselo. Lo haremos generando una instancia de aquel CoreData Stack que creamos en el tutorial anterior. Primero de todo, importamos la clase.

Creamos la propiedad que va a guardar nuestro Stack dentro de la aplicación.

Y ahora creamos la instancia dentro del método application:didFinishLaunchingWithOptions:

Oficialmente, ya tenemos CoreData dentro de nuestra aplicación. Ahora es momento de generar el ManagedObjectContext. Recuerda que el Contexto era ese intermediario entre los ManagedObject (nuestras clases) y el PersistentStoreCoordinator (el que graba en disco).

Guardar una instancia del Contexto es hiper sencillo gracias nuestro CoreDataStack. Simplemente implementa la siguiente línea a continuación de la anterior.

 ¿Y ahora qué?

Ahora tocará pasarle el contexto a nuestro primer controlador a través de un método de instancia tipo initWithContext: o simplemente, creado una instancia del mismo y pasándole nuestro recién creado contexto.

No, ni de coña, yo quiero crear una variable global para acceder al CoreDataStack cuando me dé la gana.

Singleton sí, singleton no… Hazlo como te salga de las pelotas quieras.

Creando nuestro primer controlador.

Creamos un nuevo ViewController desde Archivo -> Nuevo -> Archivo, y lo llamamos ‘CharactersTVC‘ (TableViewController). Le decimos que de momento herede de TableViewController (luego lo cambiaremos).

Le creamos una propiedad de nombre ‘context‘ y tipo NSManagedObjectContext.

Y creamos un inicializador propio.

Eso es todo amigos.

Hemos conocido las clases de CoreData, hemos generado las clases de nuestro modelo, aprendido cómo añadir métodos a dichas clases, creado nuestro Stack de Core Data en la aplicación y pasado nuestro NSManagedObjectContext al primer controlador para comenzar a cargar los datos.

Hasta aquí llega esta parte. Repasa los pasos que hemos dado antes de seguir picando código en el siguiente artículo.

Escrito por Miguel Hernández Jaso

Autor del blog. Desarrollador especializado en iOS.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Mi Gobierno me obliga a decirle que utilizo 'cookies' en mi página. Si continúa navegando, quiere decir que está conforme con ello.