En una aplicación móvil lo normal es que dispongamos de diversas vistas en la interfaz de usuario que se van abriendo unas a otras en una determinada secuencia de navegación. Por regla general los usuarios vuelven hacia atrás con el botón correspondiente y la secuencia de "navegación" por las vistas es lineal:
En la figura anterior el usuario se movería a la primera vista, luego a la segunda, y así sucesivamente, pudiendo volver hacia atrás en cualquier momento usando la interfaz de usuario.
Sin embargo una situación muy común también es que, desde cualquiera de las vistas deseemos que el usuario "salte" directamente a la primera, deshaciendo el camino pero de golpe. Por ejemplo, en la secuencia anterior podríamos desear que desde la vista #3 se pudiese volver directamente a la primera vista además de continuar a la #4. Y desde esta última poder volver también directamente a la primera, sin tener que pasar por las intermedias:
La primera cosa que se le puede ocurrir a cualquiera es crear un segue que vaya directamente desde la vista actual en la que estamos trabajando a la vista en la que queremos terminar. Es decir, en el ejemplo crearíamos dos segues desde las vistas #3 y #4 que apuntarían a la vista #1.
Si lo probamos veremos que aparentemente funciona, pero en realidad no nos estamos dando cuenta de que estamos creando un problema de rendimiento, además de utilizando mal un concepto importante dentro de la programación de interfaces de usuario móviles.
Una posible solución que se ha empleado tradicionalmente es la de proceder según el siguiente flujo:
- Crear un delegado en el View Controller de destino
- Implementar ese delegado en el View Controles de origen (es decir, desde donde partimos)
- En el método prepareForSegue ajustar el delegado de destino para que apunte al de origen.
- Al regresar empezar a lanzar métodos recursivamente en toda la pila de delegados hasta que llegues a donde necesitas llegar.
Un proceso largo, tedioso y propenso a errores.
Para solucionar este problema de una forma elegante y directa iOS nos ofrece el concepto de segues unwind, es decir, segues que están diseñados precisamente para hacer lo que necesitamos de manera automática. Estos segues conseguirán que volvamos a la vista que queramos deshaciendo la pila de vistas de manera correcta y sin causar problemas de rendimiento.
Estos segues tienen varias particularidades y cosas que pueden sorprender la primera vez que los usas, como por ejemplo:
- Normalmente cuando creas un outlet de acción para un botón XCode crea el código inicial por ti. En este tipo de segues es justo al revés: debes tener el código ya hecho y asignarlo al botón. Algo que choca bastante la primera vez.
- Otra cosa rara es que, por regla general, el código asociado a un elemento de la interfaz de usuario suele estar ubicado dentro de la misma clase que éste. Sin embargo en este tipo de acciones el código está en la clase relacionada con la vista de destino. Poco intuitivo.
El patrón de este tipo de métodos de acción es el siguiente en Swift:
@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}
y en Objective-C:
(IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
}
En el siguiente vídeo práctico explico los problemas que puede acarrear hacerlo de manera incorrecta, y luego muestro cómo crear segues de tipo unwind para hacer el regreso entre vistas de la manera apropiada:
Para saber más: Apple Developer - Technical Note TN2298 - Using Unwind Segues