Saltar a contenido

Ejercicio parte II. recuperar los datos

Info

Esta sección es un ejercicio a seguir paso a paso que vale 0,5 puntos de la nota del bloque de iOS

Vamos a añadir una pantalla donde se puedan consultar las notas que tenemos almacenadas. Las listaremos en una table view y por el momento se verán todas, no se podrán filtrar (añadiremos esa posibilidad cuando veamos la sintaxis de las "consultas" o fetch requests).

Para recuperar todas las instancias de una entidad como un array debemos crear y ejecutar una fetch request sin "predicado" (sin condiciones, como si fuera un SELECT sin WHERE), por ejemplo para listar todas las Notas haríamos algo como:

//IMPORTANTE: estamos poniendo los tipos de request y results para que se vea cuáles son
//pero el compilador no nos obligará a ponerlos
let request : NSFetchRequest<Nota> = Nota.fetchRequest()
//la línea anterior la podríamos poner también como
//let request = NSFetchRequest(entityName:"Nota")
//es probable que lo veáis así en muchos libros/ejemplos de código

//ejecutamos la query
//suponiendo que "miContexto" sea el contexto de persistencia
let results : [Nota] = try! miContexto.fetch(request)

Vamos a hacer esto en nuestra app, aunque necesitaremos enlazar este código con la parte de UI.

La interfaz de usuario

Sigue estos pasos:

  • Crear el Tab Bar Controller: teniendo seleccionada la única pantalla de la aplicación, ve al menú y selecciona Editor > Embed In > Tab Bar Controller. Se creará el tab bar controller, por el momento con una única "solapa" que será la pantalla de creación de notas
  • En la pantalla de creación de notas, pulsa sobre el item de la barra inferior para editarlo, y ponle como Title por ejemplo Nueva, para que se vea que es la pantalla de creación de notas
  • Crear la pantalla para listar notas: Arrastrar al storyboard un Table view controller. Recuerda que es una especie de tabla a “pantalla completa”.
  • Vincular la nueva pantalla al tab bar controller: hacer Ctrl+Arrastrar desde la pantalla del tab bar hasta la de listado de notas. En el menú contextual elegir como tipo del segue el de, View Controllers (bajo Relationship Segue).
    • Cambia el título del item de la barra inferior para que ponga "Lista" o algo similar.
  • Vamos a configurar la interfaz de la nueva pantalla
    • Cambia el aspecto del prototipo de la tabla: pulsa sobre la celda prototipo de la tabla, y en las propiedades cambia el Style a `Basic
    • Pon un reuse identifier: pon algún Identifier por ejemplo MiCelda (recuerda que este identificador se emplea luego en el código para solicitar al sistema instancias reutilizables de celdas)
  • Ahora vamos a configurar el controlador de la pantalla
    • Primero tenemos que crear un controlador (File>New>File...). De las plantillas que aparecen usa Cocoa Touch Class, así Xcode generará código por nosotros. La clase se debe llamar ListaNotasController y heredará de UITableViewController.

  • Ahora hacer que la nueva clase sea el controlador de la pantalla de listado de notas:
    • en el storyboard tienes que seleccionar la pantalla de listado de notas (primero de los iconos de la barra superior, el de fondo amarillo)
    • En el Identity Inspector (cuarto de los iconos del panel de la derecha de Xcode, ), como Class ponerListaNotasController`

Pon un print("hola soy ListaNotasController") en el viewDidLoad del ListaNotasController para comprobar que efectivamente se usa esta clase como controlador de la nueva pantalla.

Prueba a ejecutar el proyecto para ver que funciona el cambio de pantallas en el tab bar controller y que efectivamente en la pantalla de lista aparece el print hecho por ListaNotasController.

El código de la pantalla de listado

En la tabla vamos a mostrar un array de notas. Lo primero será definir una propiedad para almacenarlas en la clase ListaNotasController

//RECUERDA que hace falta este import al principio del archivo
import CoreData

class ListaNotasController: UITableViewController {
   var listaNotas : [Nota]!

}

Solo nos queda rellenar el array de notas. En ListaNotasController crea un método

override func viewWillAppear(_ animated: Bool) {

}

Vamos a rellenarlo de código. Para recuperar datos de Core Data se usa un fetch request, que sería algo así como una consulta. para crearlo, inicializamos una instancia pasándole el nombre de la entidad resultado de la consulta. Para ejecutarlo, llamamos al método fetch del contexto. Veamos un ejemplo. Escribe el siguiente código en el viewWillAppear (Recuerda que debes sacar de algún lado el contexto de Core Data (miContexto)). Este código todavía no mostrará las notas en la tabla pero al menos sí por la consola.

let request = Nota.fetchRequest()
//ACLARACION: "miContexto" es el contexto de Core Data 
//FALTA el código que obtiene "miContexto", como se ha hecho en ejemplos anteriores
//Ejecutamos la "query"
let notas = try! miContexto.fetch(request) 
for nota in notas {
   print(nota.texto!)
}

Nótese que los fetch request usan tipos. Es decir, devuelven un conjunto de elementos de una clase determinada, en nuestro caso Nota.

Si pruebas el proyecto, al navegar a la pantalla de lista, los textos de las notas deberían aparecer en la consola de Xcode (aunque no en la pantalla del simulador).

Para que los datos de las notas aparezcan en la tabla, debes:

  • Asignar el valor devuelto por miContexto.fetch a la propiedad self.listaNotas, que has creado antes
  • Forzar el refresco de la tabla para que aparezcan los datos. Tras asignar el valor a listaNotas, haz self.tableView.reloadData() (En un UITableViewController la propiedad tableView referencia a la tabla, no hace falta crear el outlet)
  • Modificar los métodos que ha creado Xcode:
    • numberOfSections debe devolver 1 en vez de 0, ya que la tabla tiene 1 sección
    • tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) debe devolver el tamaño del array listaNotas (propiedad count)
    • El siguiente método, que está comentado, debes descomentarlo, y hacer un par de modificaciones:
    • Donde hace el dequeReusableCell..., cambia el identificador de la celda por el que hayas elegido tú antes al crear esta pantalla (aquí se sugería MiCelda)
    • Donde pone el comentario Configure the cell... hacer que como texto de la celda aparezca el texto de la nota correspondiente
cell.textLabel?.text = self.listaNotas[indexPath.row].texto as? String