async/await en swift con Xcode 12

Andres Felipe Ocampo
6 min readJan 26, 2021

--

Muchas veces estamos luchando con la forma de anidar llamadas a servicios o incluso si los callbacks nos ayudan para gestionar ficheros con el NSFileManager, pero muchas veces hay que trabajar con hilos con GCD, con Operaciones o Thread’s, todas ellas herramientas y opciones, que nos entrega Apple, y como guinda del pastel, está al caer, la implementación de los conocidos metodos async / await de C# y Javascript que llevan muchos años ya!.

Aquí vamos a conocer la forma de trabajo de los async/await y para ello, tenemos que nuestro entorno de trabajo para entenderlo, así que manos a la obra.

Introducción

Los callbacks son bloques de funcionalidad autónomos que se pueden transmitir y utilizar en tu código. Los callbacks pueden capturar y almacenar referencias a cualquier constante y variable del contexto en el que están definidas. Los callbacks permiten que una función asíncrona acepte un parámetro que en realidad es otra función. La función se llama después de que finaliza el código de la closure, con un error o un Objeto(valor).

En nuestros proyectos implicamos una gran cantidad de programación asíncrona que utiliza closures y controladores de finalización(protocolos). Los callbacks son la forma más fácil de escribir código asincrónico. Estos son complicados añ principio y no pensar en Objetive -C que son una auténtica locura de entender, pero son tan poderosos y expresivos que se utiliza como una metodología generalizada en el desarrollo de una aplicación para iOS.

async / await, es una extensión de lenguaje para hacer que la programación asincrónica sea mucho más natural y menos propensa a errores. Esto se inspira en una propuesta anterior escrita por Oleg Andreev , disponible aquí.

Hace poco vengo de hacer un curso intensivo sobre concurrencia en iOS con Genar Codina Reverter (Senior Mobile Architect en everis), y pondré la lista de los temas vistos y añadiremos async / await como una opción más, fijaros que maravilla !!.

  • Threads
  • Queues
  • Groups
  • Semaphores
  • Operations
  • Operations Queues
  • Asynchronous operations
  • Operation dependencies
  • Cancelling operations
  • Async / Await

Entorno de trabajo

  1. Lo primero que debemos hacer es temer la ultima version del Xcode 12.3 descargada de la AppStore, una vez eso, comprobar las commands tool a esta version y no otra (sobre todo si tienes otras versiones de xcode instaladas).
  2. Descargar un ficheros toolchains desde aquí

3. Luego activar dicho plugin en el apartado Preferences de Xcode y el TabView de Components

4. Por último activar un flag modo experimental en nuestro proyecto

-Xfrontend -enable-experimental-concurrency

Listo!! con esto ya podemos picar un poco y experimentar con async / await

Proyecto de swift con Xcode 12.3 + Toolchains (Swift Development Snapshot)

He montado un proyecto con un patron seudo VIPER, para establecer una serie de casos a analisar lo podéis ver aquí, el objetivo principal no es replicar todos los problemas analisados sino cetrarnos en la implementación y entendimiento de async / await.

Problemas comunes con las API basadas en bloques

  1. Pirámide de Doom

Todos nos programado y encontrado con callbacks de llamada de red anidadas que se parecen a esto:

2. Verbosidad y manejo de errores al estilo antiguo

El manejo de errores se vuelve difícil y muy detallado:

3. Problemas de continuidad en el hilo principal (GCD + Thread’s)

Olvidarse de dispatch_async de nuevo a el callback correcto conduce a problemas muy difíciles de depurar que pueden manifestarse esporádicamente o en algunas partes no relacionadas del programa.

Propuesta y solución async / await

Una de las mejores soluciones al problema del infierno de devolución de llamada es async / await, a menudo conocido como funciones asíncronas, éstas permite escribir código asincrónico como si fuera código síncrono en línea recta. El concepto de async / await es simple:

  1. Permite la ejecución imperativa de código asincrónico, es decir, en lugar de usar devoluciones de llamada para manejar los valores de retorno cuando se completa una operación asincrónica, simplemente devuelve el resultado a otra función normal y el compilador hace el resto para tí.

Las funciones pueden optar por la semántica asíncrona usando la palabra clave async clave y reemplazando el argumento de cierre con el tipo de retorno habitual:

Vamos a ver las partes del codigo que cambiarían implementando async / await

en la primera parte del código tenemos un método que usa callback,eso ya lo tenemos claro, en la segunda parte del codigo he usado la palabra clave @asyncHandler, ésta es la forma en la que vamos a gestionar un manejador asíncrono y que contendrá nuestos métodos asíncronos invocados y usamos para ello la palabra clave await delante de la invocación del método.

En el resto del código, observaremos la implementacion de la palabra clave async, fijaros como se elimina los callback’s de los metodos y retorna un objeto de manera asíncrona (genial no??), la palabra clave async se coloca despues del cierre de los paréntesis y luego se le indica que debe retornar, mmmm… pero no necesariamente debe retornar algo podría seguir trabajando con callback’s como el método que anida todo, ésto es velocidad y seguimiento de llamadas según se espera.

El código asincrónico comienza a ejecutarse en el mismo orden en que se escribió. Es posible que algunas operaciones deban comenzar una vez finalizadas otras operaciones, mientras que otras deben ejecutarse en paralelo. Al usar await en los lugares apropiados, puede especificar qué operaciones esperan a cuáles.

Ten en cuenta que await no bloquea el hilo, solo le dice al compilador que organice las llamadas restantes como una continuación de la operación esperada. No hay riesgo de bloqueo interno de Thread’s cuando se usa await y no es posible usarlo para hacer que el hilo actual espere el resultado.

Conclusión

async / await no es algo nuevo en absoluto. Microsoft ya lo implementó en .Net, JavaScript también es compatible con esta función. En lo que respecta a Swift, los desarrolladores propusieron agregar esta función durante muchos años y finalmente fue aprobada.

Las funciones asincrónicas son una gran noticia para los desarrolladores de Swift. El gran beneficio de este enfoque es que el código asincrónico se escribe de la misma manera que el código de sincronización , lo cual es simplemente espectacular, para ver el codigo fuente podéis verlo aquí.

--

--

Andres Felipe Ocampo
Andres Felipe Ocampo

Written by Andres Felipe Ocampo

Digital Manager and Sr Lead iOS Engineer

No responses yet