Introducción: por qué es importante saber trabajar con HTTP en Swift
\nLas aplicaciones modernas para móviles y escritorio rara vez existen de forma aislada. Prácticamente cualquier aplicación —desde un widget del clima hasta un cliente bancario— intercambia datos con un servidor. Para ello se utiliza el protocolo HTTP, y en el lado de Swift (iOS/macOS) la herramienta principal es el framework Foundation y su clase URLSession.
En este artículo analizaremos cómo crear correctamente un cliente HTTP en Swift: desde una simple solicitud GET hasta el manejo complejo de errores y el trabajo con JSON. El material será útil tanto para principiantes que recién se familiarizan con el desarrollo en iOS, como para desarrolladores experimentados que deseen sistematizar sus conocimientos.
\nAbordaremos el enfoque moderno utilizando async/await (Swift 5.5+), que hace que el código sea limpio y legible, y también tocaremos los métodos clásicos con closures (completion handlers) para compatibilidad inversa.
Fundamentos de URLSession: creación y configuración
\nLa clase URLSession es el "director" principal de las solicitudes de red en Swift. Gestiona las conexiones, el almacenamiento en caché y la autenticación. Antes de hacer solicitudes, es necesario crear una instancia de la sesión.
Tipos de sesiones
\n- \n
- Compartida (singleton):
URLSession.shared— una sesión simple sin personalización. Adecuada para solicitudes básicas. \n - Predeterminada:
URLSession(configuration: .default)— permite configurar tiempos de espera, caché y encabezados. \n - Efímera:
URLSession(configuration: .ephemeral)— no guarda caché ni cookies en el disco. Ideal para datos privados. \n - En segundo plano:
URLSession(configuration: .background(withIdentifier:))— para descarga/envío de datos en segundo plano, incluso cuando la aplicación está minimizada. \n
import Foundation\n\n// Sesión simple\nlet sharedSession = URLSession.shared\n\n// Sesión personalizada con tiempo de espera de 30 segundos\nlet config = URLSessionConfiguration.default\nconfig.timeoutIntervalForRequest = 30\nconfig.timeoutIntervalForResource = 60\nlet customSession = URLSession(configuration: config)\n\n\nCreación y envío de solicitudes HTTP
\nLa solicitud se forma con la clase URLRequest. Contiene la URL, el método HTTP, los encabezados y el cuerpo de la solicitud. Veamos los métodos principales: GET y POST.
Solicitud GET con async/await (enfoque moderno)
\nA partir de Swift 5.5, Apple agregó soporte para funciones asíncronas (async/await). Esta es la forma más concisa y segura de trabajar con la red.
func fetchData(from urlString: String) async throws -> Data {\n guard let url = URL(string: urlString) else {\n throw URLError(.badURL)\n }\n \n var request = URLRequest(url: url)\n request.httpMethod = "GET"\n request.setValue("application/json", forHTTPHeaderField: "Accept")\n \n let (data, response) = try await URLSession.shared.data(for: request)\n \n // Verificamos el estado HTTP\n guard let httpResponse = response as? HTTPURLResponse,\n (200...299).contains(httpResponse.statusCode) else {\n throw URLError(.badServerResponse)\n }\n \n return data\n}\n\n// Uso:\nTask {\n do {\n let data = try await fetchData(from: "https://api.example.com/users")\n print("Recibidos \\(data.count) bytes")\n } catch {\n print("Error: \\(error.localizedDescription)")\n }\n}\n\n\nSolicitud POST con cuerpo JSON
\nPara enviar datos al servidor se utiliza el método POST. El cuerpo de la solicitud generalmente se codifica en JSON.
\n\nstruct User: Codable {\n let name: String\n let email: String\n}\n\nfunc createUser(_ user: User) async throws -> Data {\n let url = URL(string: "https://api.example.com/users")!\n var request = URLRequest(url: url)\n request.httpMethod = "POST"\n request.setValue("application