WebSocket en Swift: tiempo real para iOS y macOS

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course
```html

Introducción a WebSocket en Swift: de la teoría a la práctica avanzada

En el desarrollo móvil moderno, la interacción en tiempo real se ha convertido no solo en una característica, sino en una necesidad. Los usuarios esperan que los chats, los feeds de noticias, las cotizaciones y las notificaciones se actualicen al instante, sin gestos innecesarios de pull-to-refresh. WebSocket es el protocolo que permite establecer una conexión bidireccional permanente entre el cliente (tu aplicación en Swift) y el servidor.

En este artículo, iremos más allá del simple "Hello, World!" y analizaremos técnicas avanzadas para trabajar con WebSocket en Swift para las plataformas iOS y macOS. Aprenderás cómo configurar una conexión confiable, manejar escenarios complejos (pérdida de conexión, reconexión, modo en segundo plano) y construir una arquitectura que soporte la carga de una aplicación real de bolsa o un chat con miles de usuarios.

Analizaremos tanto el nativo URLSessionWebSocketTask (iOS 13+), como la popular librería Starscream para versiones anteriores. El código será completamente funcional y listo para integrar.



1. Configuración avanzada de un cliente WebSocket en Swift

Empecemos por lo fundamental. En lugar de una conexión trivial, crearemos un gestor que administre el ciclo de vida de la conexión, maneje errores y soporte la reconexión automática.



1.1. Gestor con reconexión automática (Reconnect)

Implementaremos la clase WebSocketManager, que utiliza URLSessionWebSocketTask. La característica clave es una demora exponencial entre los intentos de reconexión, para no sobrecargar el servidor.



import Foundation

final class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private var session: URLSession? private var isConnected = false private var reconnectAttempt = 0 private let maxReconnectDelay: TimeInterval = 30 // Demora máxima 30 seg private let baseDelay: TimeInterval = 2 // Demora base 2 seg var onMessageReceived: ((String) -> Void)? var onConnectionStateChanged: ((Bool) -> Void)? func connect(url: URL) { session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue()) let request = URLRequest(url: url, timeoutInterval: 10) webSocketTask = session?.webSocketTask(with: request) webSocketTask?.resume() receiveMessage() } private func reconnect() { guard let url = webSocketTask?.originalRequest?.url else { return } let delay = min(baseDelay * pow(2.0, Double(reconnectAttempt)), maxReconnectDelay) print("Reconectando en \\(delay) segundos... (Intento \\(reconnectAttempt + 1))") DispatchQueue.global().asyncAfter(deadline: .now() + delay) { [weak self] in self?.connect(url: url) self?.reconnectAttempt += 1 } } private func receiveMessage() { webSocketTask?.receive { [weak self] result in switch result { case .success(let message): switch message { case .string(let text): self?.onMessageReceived?(text) case .data(let data): if let text = String(data: data, encoding: .utf8) { self?.onMessageReceived?(text) } @unknown default: break } self?.reconnectAttempt = 0 // Reinicio del contador al recibir exitosamente self?.receiveMessage() // Seguimos escuchando case .failure(let error): print("Error al recibir: \\(error.localizedDescription)") self?.disconnect() self?.reconnect() } } } func send(text: String) {```

Blogs

Book Recommendations