Introducción: ¿Por qué los desarrolladores de Swift todavía buscan en Google solicitudes HTTP?
Si alguna vez has escrito una aplicación en Swift que se comunica con un servidor, seguro que te has enfrentado a esta pregunta. Parecería, ¿qué tiene de complicado? Envías una solicitud, recibes una respuesta. Pero en la práctica, uno de cada dos desarrolladores (incluso con experiencia) abre Stack Overflow y busca: "How to make HTTP request in Swift?". Y esto es normal.
¿Por qué? Porque el ecosistema de Swift cambia. Ayer mismo todos escribían closures y delegados. Hoy — async/await. Y mañana, quizás, aparezca algo más. En 2025, los enfoques para las solicitudes de red se han consolidado, pero el diablo, como siempre, está en los detalles: gestión de hilos, manejo de errores, cancelación de solicitudes, pruebas.
En este artículo analizaremos las mejores prácticas reales para realizar solicitudes HTTP en Swift — desde el URLSession básico hasta técnicas avanzadas con async/await y bibliotecas. Aprenderás a escribir código de red limpio, seguro y eficiente. ¡Vamos allá!
1. URLSession: El fundamento que todos deben conocer
Empecemos por lo principal. En la biblioteca estándar de Swift (Foundation) está todo lo necesario para trabajar con HTTP — la clase URLSession. Recuerda: para el 90% de las tareas no necesitas bibliotecas de terceros. URLSession es una herramienta potente, flexible y nativa.
1.1. Solicitud GET simple (estilo antiguo)
Recordemos cómo se hacía antes. Este código aún puedes encontrarlo en proyectos heredados:
let url = URL(string: "https://api.pythonlib.ru/users")!let task = URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { print("Error: \\(error.localizedDescription)") return } guard let data = data else { print("Sin datos") return } // Trabajamos con data print("Bytes recibidos: \\(data.count)")}task.resume()Este código funciona. Pero tiene desventajas:
- Callback hell — si necesitas hacer una cadena de solicitudes, el código se vuelve ilegible.
- Fugas de memoria — es fácil olvidar
weak selfen el closure. - Difícil de cancelar — necesitas guardar una referencia a
task.
En 2025 escribimos de otra manera.
1.2. Solicitud GET moderna con async/await
A partir de Swift 5.5 (iOS 15, macOS 12), tenemos structured concurrency. Esto lo cambia todo:
func fetchUsers() async throws -> [User] { let url = URL(string: "https://api.pythonlib.ru/users")! let (data, response) = try await URLSession.shared.data(from: url) guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw URLError(.badServerResponse) } return try JSONDecoder().decode([User].self, from: data)}Hermoso, ¿verdad? Sin closures, sin resume(). El código se lee como síncrono, pero se ejecuta de forma asíncrona. Este es el estándar de facto en 2025.
2. Solicitud POST: enviando datos al servidor
Ahora enviemos datos. Supongamos que necesitamos crear un nuevo usuario.
2.1. POST con cuerpo JSON
func createUser(name: String, email: String) async throws -> User { let url = URL(string: "https://api.pythonlib.ru/users")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let body = ["name": name, "email": email] request.httpBody = try JSONSerialization.data(withJSONObject: body) let (data, response) = try await URLSession.shared.data(for: request) // Procesamiento de la respuesta... return try JSONDecoder().decode(User.self, from: data)}
Blogs
Book Recommendations
Leer también