Persistencia en dispositivos móviles - iOS
  • Introduction
  • Persistencia básica
    • El sistema de archivos
    • Serialización de clases
    • Property Lists
    • Preferencias de usuario
    • Ejercicios
  • SQLite
    • Introducción a SQLite en iOS
    • El API básico de SQLite
    • Frameworks de terceros
    • Ejercicios
  • ¡Hola Core Data!. Una aplicación de ejemplo
    • Introducción a Core Data
    • El stack de Core Data
    • Las entidades
    • Recuperar los datos
  • Modelos de datos en Core Data
    • Crear modelos
    • Entidades con clases propias
    • CRUD
    • Ejercicios
  • Más sobre modelos de datos
    • Tipos de datos transformables
    • Validaciones
    • El ciclo de vida de los objetos gestionados
    • Deshacer y rehacer operaciones
    • Ejercicios
  • Búsquedas en Core Data
    • Predicados
    • Ordenación
    • Ejercicios
  • Tablas en Core Data
    • El fetched results controller
    • Inicializar el "fetched results controller"
    • Mostrar los datos en la tabla
    • Refrescar la tabla
    • Secciones de tabla automáticas
    • Ejercicios
  • Migraciones de datos
    • Qué son las migraciones de datos
    • Versiones del modelo de datos
    • Migraciones ligeras
    • Migraciones pesadas
    • Ejercicios
    • Apéndice: migraciones en iOS<=9
  • Contextos múltiples
    • Múltiples contextos para trabajos en background
    • Comunicación entre contextos
    • Contextos anidados
    • Ejercicios
  • Persistencia como servicio
    • Backend as a Service
    • Gestión de usuarios en Firebase
    • Persistencia en Firebase
    • Ejercicios
  • Arquitecturas de aplicaciones en iOS
    • Model/View/Controller
    • Model/View/Presenter
    • Model/View/ViewModel
    • VIPER
    • Ejercicios parte I
    • Ejercicios parte II
    • Ejercicios parte III
Powered by GitBook
On this page

Was this helpful?

  1. Tablas en Core Data

Refrescar la tabla

Tal y como está ahora el código si creamos un nuevo mensaje este no aparece en la tabla. Pero podemos resolverlo de forma sencilla con el fetched results controller, ya que este está “suscrito” a los cambios que se producen en el contexto de persistencia, siempre que afecten a los contenidos en su fetch request.

El fetched results controller avisará a su vez de estos cambios a su delegate. Para simplificar, haremos que este sea el view controller, aunque podría ser cualquier clase.

//En el viewDidLoad, tras crear el fetched results controller
self.frc.delegate = self;

Lo anterior, en lugar de por código, se puede hacer gráficamente en Xcode con el connections inspector.

Por tanto tendremos que pasar a implementar el protocolo correspondiente, ya que el fetched results controller llamará a una serie de métodos cuando se modifique el contexto. Lo primero es indicarlo en la cabecera de la clase:

import UIKit
import CoreData

class MiController : UITableViewController, NSFetchedResultsControllerDelegate {
 ...
}

El protocolo tiene cuatro métodos que vamos a ver a continuación.

Cuando se van a modificar los datos y cuando ya se han modificado el fetched results controller avisará a su delegate llamando a controllerWillChangeContent y controllerDidChangeContent, respectivamente. Podemos aprovechar estos dos métodos para llamar al beginUpdates() y endUpdates de la tabla. De este modo si se modifican varias filas "de golpe" la animación se hará de forma conjunta.

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    self.tableView.beginUpdates()
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    self.tableView.endUpdates()
}

Cuando se ha modificado algún objeto del contexto y esta modificación afecte a los resultados del fetched results controller se llamará al método más complejo del protocolo: controller(_:didChange:at:for:newIndexPath:). El código del método va a ser algo largo porque aquí tenemos que tratar con los cuatro tipos de modificaciones posibles: .insert, .move, .delete y .update.

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch type {
    case .insert:
        self.tableView.insertRows(at: [newIndexPath!], with:.automatic )
    case .update:
        self.tableView.reloadRows(at: [indexPath!], with: .automatic)
    case .delete:
        self.tableView.deleteRows(at: [indexPath!], with: .automatic)
    case .move:
        self.tableView.deleteRows(at: [indexPath!], with: .automatic)
        self.tableView.insertRows(at: [newIndexPath!], with:.automatic )
    }
}

Como vemos, el código es bastante directo, simplemente hay que trasladar a la vista de tabla lo que nos está diciendo el fetched results controller: si se ha insertado un dato insertamos una fila, si se ha borrado la borramos, etc.

El último de los métodos del protocolo se usa cuando se modifican las secciones de la tabla. Todavía no hemos visto cómo decirle al fetched results controller que cree una tabla con secciones, pero no lo necesitamos para ver ya cómo se modifican.

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
    switch(type) {
    case .insert:
        self.tableView.insertSections(IndexSet(integer:sectionIndex), with: .automatic)
    case .delete:
        self.tableView.deleteSections(IndexSet(integer:sectionIndex), with: .automatic)
    default: break
    }
}
PreviousMostrar los datos en la tablaNextSecciones de tabla automáticas

Last updated 6 years ago

Was this helpful?