UITableView y UITableViewCell en UIKit con Swift en Español - Curso iOS
UITableView sirve para poder mostrar un listado de información. Cada elemento de nuestra UITableView lo representamos con una UITableViewCell. Hoy aprendemos a cómo crear por código una UITableView, con celda custom, diferentes headers, secciones, etc
Hoy en SwiftBeta vamos a ver las famosas UITableView y UITableViewCell. Vamos a crear una app que muestra un listado de devices. Estos devices estarán separados por secciones dentro del UITableView, y podremos ver todos ellos al hacer scroll. También crearemos una vista custom que representará nuestra celda, y lo haremos paso a paso. Aparte de aprender a crear TableViews, también sacaremos toda responsabilidad de nuestro ViewController para dejar un código más mantenible y escalable, al final nuestro ViewController tendrá muy pocas líneas de código. Si te gustan los videos del canal y quieres apoyarlo, suscríbete. De esta manera seguiré creando contenido cada semana.
Creamos el proyecto en Xcode
Lo primero de todo que vamos hacer es crear el proyecto en Xcode. Acuerdate que estamos usando UIKit, es por eso que debes seleccionar Storyboard en Interface.
Una vez hemos creado el proyecto nos vamos al ViewController. Allí dentro vamos a crear nuestra primera instancia de UITableView.
Hemos aprovechado y hemos añadido nuestro UITableView a la View del ViewController. También hemos aplicado constraints para que la TableView ocupe todo el espacio de la vista del ViewController.
Creamos la estructura de datos a mostrar en nuestra UITableView
A continuación, vamos a crear una Struct (podemos hacerlo en un fichero aparte o en el mismo fichero del ViewController) que va a representar la información que vamos a mostrar en cada celda de nuestro UITableView. La struct la vamos a llamar Device:
Ahora que ya tenemos la struct, vamos a crear un array con información:
La constante house contiene un array que va a representar información de los devices que tengo en casa. Cada elemento de este Array será una celda en nuestro UITableView, ¿pero cómo hacemos para conectar los datos con la vista? Para hacerlo necesitamos usar la propiedad datasource de nuestro UITableView.
Conformamos el protocolo UITableViewDataSource
Esta propiedad espera que el objecto, la instancia que le asignemos aquí, conforme el protocolo UITableViewDataSource. Y esta instancia, sabe como proporcionar los datos a la vista, ya que debe implementar unos métodos que son obligatorios. De momento, asignamos a la propiedad dataSource de nuestro UITableView el valor de self. Y por lo tanto deberemos conformar el protocolo UIViewTableDataSource en nuestro ViewController. Esto será temporal, ya que luego lo moveremos a otra clase para que nos quede un código mucho más limpio.
Es decir, deberíamos tener el siguiente código implementado:
Vemos que aparece un error, esto es correcto ya que hemos añadido UITableViewDataSource en nuestro ViewController (justo después de heredar de UIViewController), pero no lo estamos conformando todavía, falta utilizar los método mínimos para que se deje de quejar. Vamos a pulsar el button de Xcode para que nos autocomplete y desparezca el error:
Y al hacerlo, aparece en nuestro código dos método para ser rellenados:
El primer método espera el número de elementos que queremos mostrar en nuestro UITableView
El segundo método espera cómo representar visualmente la información en una celda de nuestro UITableView
Vamos a rellenar estos dos métodos, pero ¿por qué solo estos dos? estos son lo obligatorios que debemos rellenar si conformamos el protocolo UITableViewDataSource. Si navegamos hasta este protocolo podemos ver todos los métodos que podríamos implementar en nuestra clase ViewController. Spoiler: veremos algunos de estos más adelante en el video.
Rellenamos método numberOfRowsInSection
Debemos dar un valor del número de elementos que queremos mostrar en nuestra UITableView. Este es muy sencillo, bastaría con poner el número de elementos de nuestro Array:
Rellenamos método cellForRowAt indexPath
Aquí, lo que debemos hacer es preguntar a nuestro UITableView qué mostrar por cada elemento de nuestra constante house (el Array de devices que hemos creado hace uno momento). Y para ello nuestro UITableView nos retorna una celda vacía y la tenemos que rellenar con la información que queremos (como si fuera un cascaron). Cuando mostramos celdas en un UITableView, se maneja muy bien la memoria, imagina que tienes 1000 elementos que quieres mostrar, al hacer scroll, las celdas que van despareciendo se van liberando y de esta manera vamos liberando memoria de nuestro UITableView. Vamos a escribir el siguiente código:
Si probamos de compilar, vamos a obtener un crash de nuestra aplicación.
Este crash nos está ocurriendo por que a nuestra UITableView le falta información. Le falta saber qué celdas tenemos registradas en nuestro UITableView. Y si te fijas este paso no lo hemos hecho aún. Vamos hacer dos cambios:
Lo primero de todo es registrar qué tipo de celdas se pueden usar en nuestro UITableView, para hacerlo vamos a registrar una del sistema dentro del método viewDidLoad, con la siguiente línea:
A continuación, vamos a moficiar el método cellForRowAt indexPath y le vamos a añadir el identificador de celda, en nuestro caso hemos usado UITableViewCell, pero podríamos utilizar cualquier otro nombre:
Si ahora compilamos, obtenemos como resultado unas celdas vacías. Pero! fíjate que son 5 celdas vacías, las mismas que tenemos en la constante house, ahora solo faltaría rellenarla con datos:
Rellenamos información de la celda UITableViewCell
Para poder rellenar la celda, necesitamos sabe qué modelo le toca a cada celda. Y también debemos crear una instancia de UIListContentConfiguration.cell() Nos quedaría un código como el siguiente:
Si compilamos vamos a ver qué ocurre:
Ahora mismo podríamos quitar el backgroundColor de nuestro UITableView, el propósito es que se viera más claro cuántas celdas se mostraban.
Aquí hay varios puntos que me gustaría destacar, para poder mostrar la información en nuestra UITableView hemos usado UITableViewCell, pero podríamos crear nuestra propia vista para hacerlo.Vamos a ver cómo lo haríamos.
Creamos una custom UITableViewCell
Pulsamos CMD+N y creamos un fichero nuevo, en el template escogemos Cocoa Touch Class
Y le voy a poner el nombre de SwiftBetaCustomCell
Y vamos a añadir el siguiente código:
Muy importante el último método, nos serviará para poder configurar la celda. Lo siguiente que vamos hacer, es registrar esta nueva celda en UITableView, tal y como hemos hecho hace un momento con UITableViewCell:
Por último, modificamos el método cellForRowAt indexPath, ahora usaremos la nueva celda que acabamos de crear:
Conformamos protocolo UITableViewDelegate
Vamos a seguir viendo más ventajas de UITableView, podemos conformar el protocolo UITableViewDelegate para detectar eventos que pasan en nuestra UITableView. Como por ejemplo:
Cuando se pulsa una celda, esto sería muy útil para lanzar acciones. Imagina que tocamos una celda y queremos navegar a una pantalla nueva.
Podemos saber si se realiza alguna swipeActions en una celda
también el tamaño de cada celda. En nuestro ejemplo todas las celdas tienen el mismo tamaño, pero puede haber casos en que cada celda tenga un tamaño dinámico.
etc
Vamos a conformar el protocolo UITableViewDelegate para poder detectar cuando una celda es pulsada.
En este caso, si compilamos no obtenemos ningún error, ya que los métodos de UITableViewDelegate son opcionales. Vamos a implementar el método para saber que una celda se ha pulsado:
Si compilamos, cuando seleccionamos una celda se printa por consola la información de la celda.
Limpiamos código, dividimos responsabilidades
Extraemos UITableViewDataSource a una nueva clase
Nuestro ViewController está empezando a tener demasiada responsabilidad, ahora lo que vamos hacer es separar responsabilidades, vamos a intentar dejar nuestro ViewController lo más limpio posible. Pulsamos CMD+N y creamos un nuevo fichero, lo vamos a llamar SwiftBetaTableViewDataSource
SwiftBetaTableViewDataSource espera un array de modelos, estos los tenemos hardcodeados dentro de la app, pero podrían venir de alguna petición HTTP a nuestro servidor. Para hacer el video más simple, esta información la tenemos en una constante.
Extraemos UITableViewDelegate a una nueva clase
Lo siguiente que vamos hacer es extraer el UITableViewDelegate en un fichero aparte, y lo vamos a llamar SwiftBetaTableViewDataSource
Y al sacar toda esta responsabilidad de nuestro ViewController quedaría de la siguiente manera:
Limpiamos nuestro ViewController
Una vez hemos sacado todas esas responsabilidades, podemos limpiar la creación de la vista en nuestro UIViewController:
Bastante limpio! hemos borrado muchas líneas de código 👏
Vamos a ver qué más podemos hacer con las UITableViews
Añadir Headers
Podemos añadir headers y footers, a continuación vamos a ver el ejemplo de un header, para añadir el siguiente código debemos ir a la clase SwiftBetaTableViewDataSource:
Si compilamos vemos el siguiente header
vamos a añadir más secciones a nuestra UITableView. Para hacerlo necesitamos:
Más datos, un Array nuevo
Crear al método numberOfSections
Modificar todos los sitios donde extramos el valor del model. Ahora primero debemos especificar la sección para saber cuántos elementos tiene.
Diferenciar título entre secciones
Si compilamos, podemos ver
Aquí, podríamos hacer como lo que hemos hecho con la celda, crear una Custom, añadir las subvistas que quereamos, añadir un height más grande, etc
Conclusión
Hoy hemos aprendido a cómo crear una UITableView. Al principio hemos creado una celda que nos proporciona UIKit llamada UITableViewCell. Y luego hemos creado una custom, una en la que hemos podido añadir las subvistas que hemos querido. Lo siguiente que hemos hecho ha sido limpiar nuestro ViewController, hemos sacado toda responsabilidad a otras clases, y finalmente hemos creado un header para cada sección de nuestros datos de la TableView. Se podrían hacer muchas más cosas, pero como video introductorio lo dejaremos aquí.
UIKit es el framework de UI que usamos para crear las pantallas de nuestras app. Con la llegada de SwiftUI, poco a poco hay más apps que están migrando a esta tecnologia, pero aún así saber UIKit es indispensable en una empresa que aún trabaje con UIKit
Aprende a usar childViewControllers en tu app iOS. A medida que creamos una app podemos extraer responsabilidades en ViewControllers. De esta manera simplificamos mucho nuestro código y lo podemos reutilizar en múltiples partes de nuestra app.