WebSocket en Swift : création d'applications temps réel de niveau avancé
\nDans le développement mobile moderne, l'interaction en temps réel est devenue non seulement un atout, mais une nécessité. Cotations financières, jeux en ligne, messageries, édition collaborative de documents — tout cela nécessite un transfert instantané de données entre le client et le serveur. Dans l'écosystème Apple, les frameworks Swift et Foundation fournissent des outils puissants pour travailler avec le protocole WebSocket. Dans cet article, nous examinerons des techniques avancées : du natif URLSessionWebSocketTask à la gestion personnalisée des erreurs, au multithreading et à l'optimisation des performances.
1. Implémentation native de WebSocket via URLSessionWebSocketTask (iOS 13+)
\nDepuis iOS 13, Apple offre un support intégré de WebSocket via URLSessionWebSocketTask. C'est la méthode privilégiée car elle ne nécessite pas de dépendances tierces et est profondément intégrée au système de gestion des connexions.
1.1. Création et configuration de la session
\nPour commencer, créons un gestionnaire WebSocket avec prise en charge de la reconnexion et du pooling de threads :
\nimport Foundation\n\nclass WebSocketManager: NSObject {\n private var webSocketTask: URLSessionWebSocketTask?\n private var session: URLSession!\n private let queue = DispatchQueue(label: "com.websocket.queue", qos: .userInitiated)\n private var isConnected = false\n \n override init() {\n super.init()\n let config = URLSessionConfiguration.default\n config.waitsForConnectivity = true\n config.timeoutIntervalForResource = 300\n session = URLSession(configuration: config, delegate: self, delegateQueue: nil)\n }\n \n func connect(url: URL) {\n webSocketTask = session.webSocketTask(with: url)\n webSocketTask?.resume()\n receiveMessage()\n }\n \n func disconnect() {\n webSocketTask?.cancel(with: .normalClosure, reason: nil)\n isConnected = false\n }\n}\n\n1.2. Gestion avancée des messages avec typage
\nCréons une énumération pour les types de messages et implémentons l'analyse :
\nenum WebSocketMessage {\n case text(String)\n case data(Data)\n case ping\n case pong\n case error(Error)\n}\n\nextension WebSocketManager: URLSessionWebSocketDelegate {\n func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {\n isConnected = true\n print("WebSocket connecté")\n }\n \n func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {\n isConnected = false\n print("WebSocket fermé : \\(closeCode)")\n // Reconnexion automatique après 5 secondes\n DispatchQueue.global().asyncAfter(deadline: .now() + 5) { [weak self] in\n self?.reconnect()\n }\n }\n \n private func receiveMessage() {\n webSocketTask?.receive { [weak self] result in\n switch result {\n case .success(let message):\n self?.handleMessage(message)\n self?.receiveMessage() // Réception cyclique\n case .failure(let error):\n self?.handleError(error)\n }\n }\n }\n \n private func handleMessage(_ message: URLSessionWebSocketTask.Message) {\n switch message {\n case .string(let text):\n processText(text)\n case .data(let data):\n processData(data)\n @unknown default:\n break\n }\n }\n}\n\n2. Travail avancé avec le multithreading et les performances
\nLes applications temps réel nécessitent des performances élevées. Examinons les optimisations clés.
\n\n2.1. File d'attente de messages thread-safe
\nclass ThreadSafeMessageQueue {\n private var queue = [WebSocketMessage]()\n