Saltar al contenido →

Diario Swift – Día 4 – Core Data, NSBatchUpdateRequest y NSBatchDeleteRequest

Apple añadió NSBatchUpdateRequest a Core Data cuando lanzó iOS 8. Con iOS 9, Apple nos proporcionó NSBatchDeleteRequest. Estos nuevos métodos todavía no están documentados por Apple, por lo tanto, utilizarlos puede resultar algo complicado.

En este artículo, compartiré contigo mi experiencia al utilizar estos métodos y lo que he podido leer en distintos sitios sobre este tema.

¿Por qué utilizar operaciones en lote?

Por dos motivos:

1. Son más eficientes.

Puedes leer en este artículo el resultado de una comparativa de tiempos entre eliminar objetos a la antigua usanza y utilizando NSBatchDeleteRequest. La diferencia en memoria queda patente también en la gráfica del artículo de Big Nerd Ranch.

2. Es más sencillo

Bueno, esto es relativamente cierto como verás con los ejemplos.

Hasta que estos métodos aparecieron, la única manera de realizar un borrado de varios objetos al mismo tiempo es hacer un Fetch Request, ir recorriendo los resultados y eliminar uno a uno utilizando el método deleteObject.

Para una actualización masiva de atributos, el funcionamiento es parecido. Primero haces un Fetch Request, recorres los resultados, y modificas uno a uno los objetos.

Estas nuevas APIs permiten realizar operaciones sobre todo el resultado del Fetch Request sin tener que recorrerlo. Estos métodos siempre se ejecutan en otro hilo, por lo tanto no bloquean la interfaz gráfica durante su ejecución. Esto tiene algunas consecuencias negativas, pero la principal es que el contexto de Core Data que estás utilizando no estará actualizado con los cambios realizados a menos que realices manualmente un “merge” de los cambios.

NSBatchDeleteRequest

Antes de la aparición de NSBatchDeleteRequest, la única manera de eliminar de forma masiva varios objetos era la siguiente:

Este código se reduce a esto:

Este método no actúa sobre el contexto sino directamente sobre el Persistent Store. El contexto no sabe que los objetos acaban de ser eliminados. No se lanzará ninguna notificación de cambio y tampoco se respetan las reglas de validaciones que tengas definidas.

Si tienes un objeto cargado en memoria, lo eliminas con NSBatchDeleteRequest, puede ser que te encuentres con que tu objeto sigue existiendo después de haber sido eliminado. Se habla un poco sobre el tema en la conferencia de Apple What’s New in Core Data de 2015.

Para solucionar esto, hay que resetear el contexto añadiendo esta línea de código justo después de “try managedContext.executeRequest(batchDeleteRequest)”:

Con esta línea de código, tu contexto volverá a estar limpio. El problema es que perderás todos los cambios que no has guardado y cualquier referencia que tengas a un objeto del contexto debe ser renovada. Por ejemplo, si estás utilizando un NSFetchedResultsController, debes realizar de nuevo un “performFetch” para obtener los últimos datos actualizados.

NSBatchUpdateRequest

NSBatchUpdateRequest te permite realizar un UPDATE sobre varios objetos en una misma consulta. Hasta su aparición, el código era mucho más complejo e ineficiente:

En este caso, el código no es mucho más sencillo, porque debes actualizar el contexto con los objetos modificados:

Después de ejecutar la operación en lote NSBatchUpdateRequest, recoges los objectIDs modificados y refrescas el objeto en el contexto en el que estás trabajando. De esta manera, tu contexto tendrá la versión actualizada. Ahora sólo te queda actualizar la interfaz gráfica por ejemplo llamando a “performFetch()”.

meme core data día 4

La verdad es que todo esto es bastante confuso y la documentación brilla por su ausencia. Te recomiendo que hagas pruebas por ti mismo y compruebes cómo funciona todo esto. Apple avisa de que estos métodos deberían ser utilizados con mucha precaución por lo tanto, si no es necesario, te desaconsejo su uso. A pesar de lo que se gana en velocidad y memoria, las consecuencias inesperadas pueden ser mucho peores.