URLSESSION en Swift en Español

URLSESSION en Swift en Español

URLSession en Swift lo usamos para realizar peticiones HTTP. Podemos usar una URL o URLRequest con distintos métodos: POST, GET, UPDATE, etc. En el post de hoy usamos el método dataTask de URLSession. Hoy en día todo desarrollador debe saber usar esta clase para realizar llamadas.

SwiftBeta
URLSession en Swift para principiantes

En este post vamos aprender sobre URLSession y lo fácil que es crear peticiones HTTP.

Cada vez que usas una aplicación como Instagram, TikTok o Twitch, estás accediendo a sus servidores para obtener información. La app hace una petición para recibir estos datos. Estos datos tienen diferentes formatos y en la mayoría de casos es JSON. Nosotros cogemos este JSON y lo traducimos para que nuestra app lo entienda y muestre esta información en las vistas de nuestra app.

Antes de todo, te voy a explicar un poco como funciona URLSession. Con esta clase podemos descargar y subir datos haciendo peticiones HTTP (Al hacer una petición llamamos a un endpoint, que tienen una URL que apuntan a un servicio de nuestro backend, por ejemplo: login o registro de un user).
Cuando la aplicación no está corriendo o cuando está suspendida podemos hacer descargas en background. Hay distintos delegados como URLSessionDelegate y URLSessionTaskDelegate (pero si no los necesitas puedes asignarlos a nil)

Puedes usar solo URLSession para hacer peticiones HTTP sencillas, pero para cosas más complejas puedes usar otras clases relacionadas con URLSession o los delegados que acabamos de mencionar. Un ejemplo sencillo sería el porcentaje que falta en descargar (o subir) un archivo.

Tipos de URLSession

URLSession tiene un singleton al que podemos acceder de esta manera:

URLSession.shared

No necesitamos crear ninguna configuración. Su uso no es muy customizable, pero cuando tenemos pocos requirimientos es una solución ideal.

Si quieres crear una URLSession con una configuración, tienes 3 tipos para escoger:

  • Default session. Se comporta como la shared session (sesión del singleton), pero aquí puedes customizarla. Podemos asignar un delegado a la sesión para obtener datos de forma incremental.
  • Ephemeral session. Son similares a la shared session pero aquí no guardamos en disco ni la cache, las cookies o los credenciales.
  • Background session. Esta sesión nos permite descargar o subir contenido en background cuando la aplicación no se está ejecutando

Tipos de tasks en URLSession

En una sesión podemos usar distintas tasks dependiendo de nuestro objetivo:

  • Data tasks. Envían y reciben objetivos tipo data. Un ejemplo muy claro sería enviar un POST o un GET y tratar los datos como si fueran JSON.
  • Upload tasks. Muy parecidas a las comentadas en el punto anterior, pero también envían datos (la mayoría de veces como si fuera un archivo, como una foto, video, etc), y también soportan subidas en background cuando la app no se está ejecutando.
  • Download tasks. Para obtener datos en formato archivo y también permite descarga y subida mientras la app no se está ejecutando.
  • WebSocket

Asincronismo y URLSession

Como casi todas las API de red, URLSession es asíncrona. Y podemos obtener los datos en nuestra aplicación de 2 maneras, dependiendo del método que llames:

  • Llamando al bloque de completion handler cuando la llamada a finalizado correctamente o con error.
  • Llamando a los métodos del delegado donde nos indica todos los datos que van llegando y cuando la transferencia se ha completado.
A partir de iOS 9.0 se añadió App Transport Security (ATS) para todas las conexiones hechas con URLSession. Es por eso que debemos modificar un campo en nuestro Info.plist
La API de URLSession es thread-safe. Puedes tener sesiones y tareas en cualquier thread.

¿Por qué es útil cachear datos? Para consumir menos recursos de red. Si repetimos una llamada (que préviamente ya hemos hecho a nuestro backend), depende de nuestra configuración de URLSession para volver a ir a red o a la caché. Si nuestro backend nos devuelve "Cache-Control" en la response de nuestra llamada, entonces URLSession cacheará esta información. Podemos cambiarlo cambiando la configuración de URLSessionConfiguration y la propiedad de requestCachePolicy ponerla a reloadIgnoringLocalCacheData o hacer que nuestra configuración sea ephemeral.
Pequeños detalles como estos te ayudarán a ir directamente a la causa del problema en lugar de perder horas buscando el problema.


Vamos a realizar nuestra primera llamada a la API de Apple para buscar música en iTunes.

let urlSessionConfiguration = URLSessionConfiguration.default
let urlSession = URLSession(configuration: urlSessionConfiguration)
let url = URL(string: "https://itunes.apple.com/search/media=music&entity=song&term=avicii")

urlSession.dataTask(with: url!) { data, response, error in
    print("Data \(String(describing: data))")
    print("Response \(String(describing: response))")
    print("Error \(String(describing: error))")
}.resume()
Código Swift de petición HTTP con URLSession y URL

Para ello instanciamos URLSession con la configuración por defecto. La instancia urlSession tiene distintos métodos que podemos usar para realizar la llamada a red. Podemos pasarle como parámetro una URL o una URLRequest. Para hacerlo más sencillo solo le pasamos la URL (más abajo veremos cómo hacer una petición HTTP con URLRequest).

Dato curioso, en el response hay un campo que es el "Cache-Control" que comentábamos antes, indicando el tiempo que tiene que pasar hasta que vuelva hacer una llamada a red. El campo "max-age" es el tiempo que se debe cachear una respuesta:

"Cache-Control" = (
   "max-age=7404"
);

Cuando ejecutamos el método dataTask(with:), tenemos un closure donde recibiremos:
- Los datos
   - La respuesta (con el status y los headers)
   - El error (en caso de que tuvieramos un fallo)

También podríamos a haber usado URLRequest y el resultado sería exactamente el mismo:

let urlRequest = URLRequest(url: url!)

urlSession.dataTask(with: urlRequest) { data, response, error in
    print("Data \(String(describing: data))")
    print("Response \(String(describing: response))")
    print("Error \(String(describing: error))")
}.resume()
Código Swift de petición HTTP con URLSession y URLRequest

Con URLRequest tenemos más flexibilidad, tenemos propiedades como httpMethod para especificar si queremos POST, GET, PUT, DELETE, etc. También tenemos la posibilidad de añadir un httpBody, headers, etc. Como ves es mucho más configurable que solo añadir una URL.

En el siguiente post te explicaré como transformar los datos que recibimos y transformarlos en algo que entendamos. Es decir, pasaremos de JSON a nuestros objetos de domino. Así podremos coger esta información, manipularla, combinarla, mostrarla en nuestra UI, etc.

Como siempre puedes encontrar el código en Github


Hasta aquí el post de hoy, gracias por leernos! 🤓
Si tienes preguntas no dudes en contactar con nosotros a través de Twitter

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


Network