Aprende a usar UIKit en Xcode, con Storyboard, Autolayouts y UIViewControllers
Aprende a usar UIKit en Xcode, con Storyboard, Autolayouts y UIViewControllers

Introducción a UIKit - Storyboards, AutoLayout, ViewController, etc

Introducción a UIKit. Aprendemos sobre UIViewControllers y a cómo usar el Storyboard de Xcode. También a cómo distribuir vistas con Autolayout, añadiendo las conocidas constraints, una serie de normas para que cada vista sepa representarse por si sola

SwiftBeta

Tabla de contenido

Curso iOS con UIKit

Hoy en SwiftBeta vamos a empezar una nueva serie de posts sobre UIKit. Y este primero va a ser bastante completo, ya que vamos a ver:

  • Crear un proyecto de cero con UIKit,
  • Explicar por encima la arquitectura MVC
  • Crear una vista con el Storyboard. Dentro de esta vista añadiremos un UILabel y un UIButton. Al apretar el UIButton mostraremos un mensaje por consola.

¿Qué es UIKit? UIKit es uno de los frameworks de Apple para crear vistas de nuestra aplicaciones. Otro framework que podemos utilizar es el conocido SwiftUI que lanzó Apple en 2019 y que hemos visto durante los últimos meses en SwiftBeta  pero en los próximos posts pondremos foco en UIKit.

¿Por qué es importante aprender UIKit?

Es decir, si Apple ha lanzado un nuevo Framerwork para crear vistas en mis aplicaciones ¿por qué debo dedicar tiempo a UIKit? Uno de los propósitos de nuestro canal es prepararte para el mundo laboral real. UIKit fue lanzado en 2008 y tiene una gran trayectoria y mucha madurez, lleva con nosotros más de 10 años y una gran parte de las aplicaciones del App Store están creadas con UIKit.

Es por eso, que si te planteas trabajar para en una compañía como iOS Developer, es muy probable que la aplicación esté creada en UIKit (y más, si aún soporta versiones como iOS 11 en adelante, donde aún no existía SwiftUI). Aprender UIKit siempre te va a sumar en tu carrera.
Como decía, muchas aplicaciones están creadas en UIKit y algunas empiezan a integrar SwiftUI en algunas partes. Es decir, si una app tiene un 100% de UIKit, no esperes que esa app en pocos meses acabe teniendo un 100% en SwiftUI. Quizás en tu día a día te toca refactorizar pantallas que aún usan el framework UIKit.

Lo iremos viendo durante los siguientes posts, pero si tienes una app en UIKit, puedes ir migrándola poco a poco a SwiftUI. Es decir, UIKit y SwiftUI, ambos frameworks pueden convivir en la misma aplicación.

Lo siguiente que vamos a ver es a cómo crear un proyecto en Xcode pero usando el framework UIKit.

Crear un proyecto de Xcode con Interface Storyboard

Para crear un proyecto en Xcode, lo único que tenemos que hacer es crear un proyecto nuevo, y seleccionar en la parte de Interface Storyboard tal y como se muestra en la siguiente imagen.

Usamos Xcode para crear nuestra app
Usamos Xcode para crear nuestra app

Una vez creado el proyecto, nos vamos al listado de ficheros y deberíamos ver algo parecido a la siguiente imagen:

Listado de ficheros al crear un proyecto con UIKit en Xcode
Listado de ficheros al crear un proyecto con UIKit en Xcode

Vamos a ir uno por uno, sin entrar mucho en detalle:

  • AppDelegate, es el punto de entrada de nuestra app.
  • SceneDelegate, sirve para manejar distintas pantallas que podríamos mostrar a la vez dentro de nuestra aplicación (como en el caso de un iPad). También tiene métodos que se llamarán automáticamente cuando pongamos nuestra aplicación en segundo plano o la volvamos a abrir. Por ejemplo, imagina que quieres guardar información importante dentro de tu aplicación cada vez que el user pone en segundo plano tu aplicación, se podría gestionar desde el SceneDelegate
  • Main, es nuestro Storyboard. Aquí iremos creando de forma visual las pantallas de nuestra aplicación. Crearemos vistas y dentro de ellas añadiremos otras subvistas (componentes de UIKit como UIImageView, UILabel, etc). Aunque a parte de crear vistas con el Storyboard también exploraremos como hacerlo por código.
  • ViewController, un ViewController es la manera que controla UIKit para mostrar distintas vistas dentro de nuestra app. Es una clase que se encarga del ciclo de vida de las pantallas que mostramos. Normalmente, un ViewController representa una vista entera (pero no siempre es así).
  • Assets, aquí podemos añadir nuestro iconos, imágenes, colores, etc para poderlos usar dentro de nuestra aplicación.
  • LaunchScreen, es la vista que aparece mientras se está cargando nuestra aplicación. Es decir, si abres la app desde cero, se visualiza la vista que tenemos en el LaunchScreen, mientras se está inicializando nuestra aplicación.

La pieza clave de UIKit: UIViewController

Vamos a entrar un poco más en detalle en nuestro ViewController, si lo abrimos podemos ver el siguiente código:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}
Clase ViewController creada al usar UIKit en Xcode

Aquí podemos obtener información:

  • Nuestro ViewController hereda de UIViewController (esta clase está dentro del framework UIKit)
  • Tenemos un override del viewDidLoad(), es decir, podemos sobrescribir sin problema algunos métodos de la base class UIViewController.
  • UIViewController tiene varios métodos para controlar su ciclo de vida, podemos encontrar: viewDidLoad(), viewWillAppear(), viewDidAppear(), viewWillDissapear(), etc. Estos métodos serán llamados automáticamente cuando aparezca o desparezca nuestro ViewController.

Te has fijado que se llama ViewController, es decir por un lado tenemos View y por el otro lado Controller. Para entenderlo, vamos a aprovechar y explicar la arquitectura Model-View-Controller.

Arquitectura MVC

Me gustaría explicar que una de las arquitecturas que adoptó Apple para UIKit es MVC (Model-View-Controller). Esta arquitectura se divide claramente en 3 componentes clave, con 3 responsabilidades diferentes:

  • Model, es el responsable de obtener y manipular los datos que mostraremos en nuestra vista. Imagina que tienes información del perfil de un usuario. Aquí podrías tener un modelo llamado User con su nombre, foto de perfil, etc. y tener logica de dominio para extraer esta información.
  • View, es la vista donde vas a representar el modelo de datos. Si seguimos con el ejemplo anterior, sería la vista del perfil de un user. Y estaría compuesta por una UIImageView para mostrar la imagen del user, un UILabel para mostrar el nombre del user, etc
  • Controller, se encarga de unir el modelo con la vista. Cualquier acción que pase en la vista (un user pulsa un button), se envía al controller para actualizar el modelo. Si el modelo se actualiza, notifica al Controller para actualizar la vista.
Arquitectura Model View Controller en UIKit
Arquitectura Model View Controller en UIKit

Esta arquitectura tiene sus pros y sus contras, y dependerá mucho en el proyecto en el que estas trabajando (por ejemplo, el tipo de aplicación, número de developers, agreements dentro del equipo, etc). Al final una buena arquitectura te ayuda a escribir código de manera rápida, segura y testeable.

En el ejemplo que vamos hacer a continuación, que no se podrá considerar app, ya que será algo muy sencillo, añadiremos un UILabel y un UIButton a nuestra vista del ViewController, pero te preguntarás... ¿dónde está la vista?, si solo tenemos un ViewController. Pues el ViewController tiene la función de Controller y de View. Es decir, está todo unido, una de la propiedades de nuestro ViewController es la View. PERO, que sepas que podemos separar la vista del ViewController y tenerla en un fichero completamente separado. Esto también lo veremos durante la nueva serie de UIKit.

Explicado todo esto, vamos a continuar.

Creamos una vista en el Storyboard

Vamos a crear una vista muy simple en nuestro Storyboard. El propósito del post de hoy es interactuar un poco con el framework UIKit. Vamos a ver cómo distribuir las vistas y crear constraints con AutoLayout (pero solo será una brevísima instroducción, entraré más en detalle en el próximo video). Lo que vamos hacer es ir a nuestro Storyboard y vamos a añadir un Label y un Button.

Para añadir estas dos vistas podemos:

  • Pulsar el + que aparece en la parte superior detecha
  • Utilizar el shortcut CMD+SHIFT+L
Storyboard en Xcode
Storyboard en Xcode

Una vez aparece la librería de vistas de UIKit deberíamos ver algo parecido a la siguiente imagen:

Listado de subvistas que podemos añadir a nuestro Storyboard
Listado de subvistas que podemos añadir a nuestro Storyboard

Ahora vamos a arrastrar un Label y un Button. Una vez arrastrados, vemos que podemos moverlos a la posición que queramos, y hacerlos más grandes.

Inspector de Atributos de Xcode muestra las propiedades de un UILabel
Inspector de Atributos de Xcode muestra las propiedades de un UILabel

Podemos cambiar ciertas propiedades de estas vistas desde el Storybaord o por código. Por ejemplo, vamos a seleccionar el UILabel y vamos a mostrar el inspector de atributos.

Aquí, a la derecha de Xcode, nos aparecen una serie de propiedades que podemos modificar de nuestro UILabel. Vamos a cambiar algunas de ellas:

  • El texto de nuestro label, vamos a poner que se muestre el valor de SwiftBeta
  • La fuente, vamos a utilizar la fuente Large Title
  • El alineamiento del texto, ahora está alineado a la izquierda, vamos a centrarlo.

Una vez cambiado el UILabel, vamos a modificar algunas propiedades del UIButton. Pulsamos en el Button y vemos que en el inspector de atributos aparecen propiedades diferentes a las de UILabel.

En este caso, lo único que vamos hacer es cambiar el title del Button, y vamos a añadir "Suscríbete"

Inspector de Atributos de Xcode muestra las propiedades de un UIButton
Inspector de Atributos de Xcode muestra las propiedades de un UIButton

Perfecto, de momento hemos arrastrado dos vistas de UIKit en nuestro ViewController. Vamos a compilar y vamos a ver qué ocurre.

Simulador comparado con nuestra vista del Storyboard
Simulador comparado con nuestra vista del Storyboard

Vemos que nuestro UILabel y UIButton están en el centro. Ahora vamos a pulsar el icono de rotar el simulador, al pulsarlo vemos que algo pasa en nuestra vista. Los elementos que antes teníamos en el centro ahora aparecen a la izquierda. Eso pasa por que las vistas no tienen unas normas de cómo comportarte. Necesitamos añadir las conocidas constraints de Autolayout, así las subvistas sabrán exactamente como distribuirse dentro de la vista padre.

Vamos a añadir estas constraints, para hacerlo usando los Storyboards podemos hacerlo de dos maneras:

  1. Selecciona la vista en la que quieras añadir las constraints, y selecciona el button que aparece abajo a la derecha. En ese popup que aparece podemos añadir las constraints de la vista seleccionada.
Añadimos constraints a nuestras subvistas de nuestro ViewController
Añadimos constraints a nuestras subvistas de nuestro ViewController

2. Otra manera, es teniendo seleccionada la vista en la que queremos añadir constraints, mantenemos la tecla CTRL y sin soltar apretamos con el ratón. Veremos como aparece una flecha azul, si la soltamos debemos ver un popup como el siguiente.

Constraints que podemos añadir a una subvista de nuestra View
Constraints que podemos añadir a una subvista de nuestra View

En mi caso, voy a utilizar este último método. Voy a añadir las constraints para que el UIButton esté siempre en el centro de la UIView, y justo por encima está el UILabel.

El resultado sería el siguiente:

Vistas del Storyboard con constraints
Vistas del Storyboard con constraints

Si ahora compilamos la aplicación y la rotamos, vemos que cada subvista sabe como colocarse. Es decir, siempre están en el centro, ya que hemos añadido una serie de normas (las constraints).

IBOutlets y IBActions

Una vez hemos creado y distribuido las vistas en nuestra UIView de nuestro UIViewController, lo que vamos hacer es crear:

  1. Dos IBOutlets, los IBOutlets nos van a servir para conectar la parte del Storyboard con nuestra clase ViewController. De esta manera si queremos, por ejemplo cambiar el TextColor de nuestro UILabel, lo podemos hacer por código en lugar de hacerlo desde el inspector de atributos de nuestro Storyboard.
  2. IBAction, solo vamos a añadir una acción, y va a ser que cuando un user pulse nuestro UIButton se printe un mensaje por consola.

Vamos a ello, vamos a crear los dos IBOutlets, para ello vamos hacer espacio en nuestro Xcode, a la izquierda vamos a tener el Storyboard visible, y a la derecha vamos a mostrar el ViewController.
La siguiente imagen muestra un ejemplo visual para que quede más claro:

Vista separada, a un lado el Storyboard y al otro el ViewController
Vista separada, a un lado el Storyboard y al otro el ViewController

Ahora vamos a seleccionar el UILabel y vamos a mantener la tecla CTRL y arrastramos nuestro ratón (debe aparece una línea azul) hasta la línea número 11 de nuestro ViewController. En ese momento aparecerá un mensaje muy pequelo diciendo Insert Action, Outlet our Outlet Collection. Soltamos y nos aparece el siguiente popup para añadir un nombre. En mi caso lo llamo nameLabel.

Creamos nuestro primer IBOutlet
Creamos nuestro primer IBOutlet

Ahora vamos hacer exactamente lo mismo para nuestro UIButton.

Creamos nuestro segundo IBOutlet
Creamos nuestro segundo IBOutlet

Con estos dos IBOutlets ya hemos conectado la parte visual de nuestro Storyboard en nuestro ViewController. Y si quisieramos cambiar alguna propiedad podríamos hacerlo. Por ejemplo, vamos a cambiar el textColor de nuestro UILabel. Para hacerlo vamos a añadir una única línea en nuestro método viewDidLoad()

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var subscribeButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        nameLabel.textColor = .blue
    }
}
Cambiamos la propiedad de nuestro UILabel en el viewDidLoad de nuestro ViewController

Una vez hemos aprendido como conectar la parte visual con nuestro ViewController, vamos a añadir una acción para nuestro UIButton. Y para hacerlo vamos hacer el mismo proceso que antes, es decir, seleccionamos nuestro UIButton, manetenemos pulsada la tecla CTRL y arrastramos hasta el ViewController. Al conectar el UIButton con nuestro ViewController, vemos que en el popup que aparece, el tipo de Connection es Action, ahora debemos escoger un nombre para el método que se llamará cuando nuestro UIButton sea pulsado. Lo voy a llamar didTapOnSubscribeButton.

Añadimos nuestra primera IBAction
Añadimos nuestra primera IBAction

Al crear el método, nos aparece completamente vacío, voy a añadir un simple print. El código de nuestro ViewController quedaría de la siguiente manera:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var subscribeButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        nameLabel.textColor = .blue
    }
    
    @IBAction func didTapOnSubscribeButton(_ sender: Any) {
        print("🚀 ¡Button tapped!")
    }
}
Creamos un método que se llamará cada vez que se pulse el UIButton de nuestro Storyboard

Vamos a compilar nuestro código y vamos a pulsar el UIButton, así veremos un mensaje por consola. Aquí vemos dos cosas:

  • El UILabel, en lugar de tener el textColor en black está en blue, ya que lo hemos cambiado por código.
  • El UIButton al ser pulsado lanza un mensaje por la consola.
Cambios del simulador respecto a nuestra vista del Storyboard
Cambios del simulador respecto a nuestra vista del Storyboard

Conclusión

Hoy hemos visto por primera vez una pincelada de UIKit, uno de los frameworks de Apple para crear UI. Hemos visto qué es un Storyboard, Autolayout, IBOutlets, IBActions y hemos aprendido a usar cada una de ellas.

Si quieres seguir aprendiendo sobre SwiftUI, Swift, Xcode, o cualquier tema relacionado con el ecosistema Apple