Saltar al contenido →

Diario Swift – Día 2 – Core Data

Core Data es otra de las palabrejas con las que tendrás que lidiar si haces una app para iOS más o menos compleja.

Para mi aprender un nuevo lenguaje, es como aprender un nuevo idioma. Al principio, pienso en mi idioma nativo e intento traducirlo al nuevo idioma. Con práctica, tiempo y trabajo, este proceso de “traducción” acaba desapareciendo poco a poco. Mi lenguaje nativo es PHP así que he tratado de buscar similitudes entre Swift y PHP…

Conocí Core Data cuando empecé con Objective C. Poco ha cambiado con Swift y lo he agradecido porque la primera vez que me metí con Core Data, me costó adaptarme a ello.

Core Data no es MySQL

Cuando me encontré con Core Data, yo estaba buscando el equivalente a una base de datos MySQL. Core Data es un framework para manejar la persistencia de datos. Según Apple, Core Data te permite ahorrar mucho código para manejar tu modelo de datos a la hora de guardar, eliminar, recuperar datos de tu modelo. No digo que no sea verdad pero como verás más adelante, utilizar Core Data puede no ser tan intuitivo como me gustaría.

Core Data Stack

El stack de Core Data es el nombre que se le da al código generado por Xcode que consiste en crear una serie de objetos que nos permitirán guardar y recuperar información de Core Data.

Existen cuatro clases que es imprescindible conocer cuando utilizas Core Data. Las cuatro clases conforman nuestro Core Data Stack.

NSManagedObjectModel

Es el modelo de datos. Representa cada objeto de nuestro modelo con sus propiedades, relaciones, … Para dejarlo claro, es como el esquema de una base de datos de MySQL.

En el proyecto de Xcode, tendrás un archivo con la extensión “.xcdatamodeld” que contendrá el modelo de datos. Aquí se pueden crear entidades con atributos y relaciones entre ellas.

NSPersistentStore

Es el almacenamiento que utiliza nuestro stack. Se pueden escoger cuatro tipos diferentes de almacenamiento:

  • NSQLiteStoreType: Una base de datos SQLite. Es la opción más utilizada y seleccionada por defecto.
  • NSXMLStoreType: Un archivo XML. Sólo se puede utilizar para OS X, así que tampoco me interesa.
  • NSBinaryStoreType: Un archivo binario de datos. Tanto este tipo como el XML, son muy poco utilizados porque requieren ser cargados completamente en memoria antes de poder utilizarlos, lo cual requiere un consumo de recursos poco eficiente.
  • NSInMemoryStoreType: Un almacenamiento en memoria. Lo curioso aquí es que este tipo de almacenamiento no persiste si cierras tu app o apagas tu dispositivo. Por lo tanto, no es de mucha utilidad.

NSPersistentStoreCoordinator

Esta clase hace de intermediaria entre el modelo de datos (NSManagedObjectModel) y el almacenamiento (NSPersistentStore). Permite por ejemplo abstraerte del tipo de almacenamiento seleccionado. Hace las funciones de un ORM, me recuerda a Doctrine por ejemplo que me permite abstraer el tipo de base de datos que estoy utilizando.

NSManagedObjectContext

Esta clase es la más importante y la clase con la que trabajarás día a día constantemente. Representa el contexto en el que estás trabajando. Todas tus operaciones de lectura y escritura se desarrollan en el contexto. Los cambios que realices en el contexto no serán almacenados en disco hasta que hagas una llamada al método “save()”.

Un objeto está fuertemente ligado a un contexto y no puede cambiar de contexto a lo largo de su ciclo de vida. Esto se convertirá en algo muy a tener en cuenta cuando utilices en tu app múltiples hilos de ejecución y necesites acceder a un mismo objeto desde ellos y modificarlo.

Cuatro operaciones básicas: Insertar, Recuperar, Modificar y Eliminar

Voy a crear un proyecto de pruebas de Xcode para mostrar como realizar las cuatro operaciones básicas. Me voy a saltar todos los pasos previos de crear proyecto, seleccionar Core Data, … Todo esto, lo podrás conseguir tú sólo estoy seguro y sino, no dudes en preguntar en los comentarios.

Modelo de datos

Sin complicaciones, mi modelo de datos se compone de 2 entidades con una relación entre ellas.

  • Entidad: Persona
    • nombre – String
    • edad – Integer 32
  • Entidad: Marca
    • marca – String
    • ano_compra – Integer 32
  • Relación: Una persona puede ser propietaria de muchas coches (To Many) y un coche sólo tiene un propietario (To One).

Diario Swift - Día 2 - Modelo de datos

Insertar

El código no es muy complicado pero intuitivo, intuitivo no es. Primero, debes insertar en el contexto una nueva entidad del tipo que necesitas. Por eso, necesitas el primer paso para crear el tipo de entidad que necesitas, luego insertas un nuevo NSManagedObject de ese tipo. Finalmente, debes llamar al método “save()” para que tu contexto termine guardando los cambios en disco, sino ninguno de tus cambios permanecerá en el siguiente arranque de la app.

Recuperar

El siguiente paso es recuperar los datos de esa persona que acabo de crear y su coche. Así de paso, compruebo que he insertado algo realmente en la base de datos y no estoy haciendo esto para nada.

Parece que sí que hay datos por lo tanto, está funcionando todo correctamente.

Para recuperar información, he utilizado NSFetchRequest con un simple predicado. No voy a entrar en detalles en este artículo con esta clase pero es donde reposa toda la dificultad y la utilidad de Core Data. Con esta clase, podrás recuperar la información de tu base de datos. Tiene muchas posibilidades, podrás utilizar predicados con NSPredicate para filtrar tus datos, podrás ordenarlos utilizando NSSortDescriptor, limitar la cantidad de datos, …

En otro artículo, trataré de hablar de todo lo que se puede hacer con NSFetchRequest. Bueno, quizás no todo, pero sí muchas cosas.

Modificar

Posiblemente, de lo más sencillo, una vez que tienes el objeto en una variable. Modificarlo es coser y cantar.

Eliminar

Igual que con modificar, si tienes el objeto recuperado, eliminarlo es muy sencillo. Puedes ver en la consola que ya no hay personas en la base de datos, por lo tanto ha sido eliminada correctamente.

Una simple introducción

Core Data es mucho más complejo de lo que acabo de mostrarte en este artículo. Si quieres utilizarlo, tendrás que investigar NSFetchRequest, NSPredicate, … Acabarás trabajando con NSFetchedResultsController y NSAsynchronousFetchRequest. Todos estos temas son lo suficientemente amplios como para ocupar un post entero cada uno, así que hablaré de ellos más adelante.

A continuación, os dejo el código completo de mi ViewController.

  • Rafa Cosin

    saludos!!
    felicidades por tu blog gracias por tratar el coreada, como bien dices un grano en el culo.
    estoy dandole al swift después de mucha carrera en grandes sistemas, y todo conocimiento es poco.
    espero seguir leyendo.
    salud

    • Gracias a ti por leer y comentar! Estoy escribiendo un artículo sobre NSBatchDeleteRequest y NSBatchUpdateRequest que espero publicar en breve. Hay poca información sobre estos métodos y Apple no ha escrito ni siquiera documentación sobre estos métodos.

  • Isai

    Que pasaría si los datos están en diferente formulario un ejemplo primero llenas el formulario de la persona, y enseguida el del automóvil como seria la relación de las tablas (mi situación es la diferente levanto un reporte lo lleno y tomo fotos como referencio las fotos ) la verdad estoy muy acostumbrado a utilizar un ID para relacionar todo (mysql, SQLITE(Android), SqlServer, )
    y el Core Data no tengo la menor idea de hacerlo

    • Hola, gracias por dejar un comentario!

      Tu pregunta es bastante compleja para poder responderla en un comentario la verdad. Lo que debes hacer es pasar tu objecto Persona al siguiente formulario (el del automóvil). En el formulario del automóvil, debes rellenar crear un objeto automóvil y después asignar el propietario del automóvil con le objeto Persona.

      Para pasar objetos de un ViewController a otro si usas segues, puedes usar el método prepareForSegue por ejemplo e inicializar una propiedad en tu otro ViewController. También puedes trabajar con callbacks. Es un tema que depende de cada desarrollo la verdad.

      Aunque no haya ID, sí que existen relaciones. Si yo tengo un objeto “Persona”, puedo saber todos los objectos “Coche” del cual ese objeto “Persona” es “propietario”. Si tengo un objeto “Coche”, puedo saber quién es el objeto “Persona” que es “propietario”.

      • Isai

        la verdad no llevo mucho desarrollando en IOS
        y esto de Core Data se me ha echo complicado por las relaciones jejeje Gracias por el apoyo y explicación , y espero entenderle pronto a esto, aun sigo muy cuadrado con SQL jejejeje vere como lo soluciono

  • Marnathael Valdez

    Muy claro todo, te agradezco!

  • Albert Barrientos

    Lejos el mejor tutorial que encontré 🙂

    Muchas gracias ^^