Introdução ao WebSocket em Swift: da teoria à prática
Aplicativos móveis e desktop modernos exigem cada vez mais transferência instantânea de dados. Seja um chat, terminal de ações, jogo online ou sistema de monitoramento — os usuários esperam que as informações sejam atualizadas em tempo real sem atualização constante da tela. É aqui que o protocolo WebSocket entra em ação.
Ao contrário da clássica requisição HTTP, que funciona no princípio "requisição-resposta", o WebSocket estabelece uma conexão bidirecional permanente entre o cliente e o servidor. Isso significa que o servidor pode enviar dados ao cliente a qualquer momento sem uma requisição prévia. No ecossistema Apple, para trabalhar com WebSocket, estão disponíveis tanto soluções nativas (URLSessionWebSocketTask) quanto bibliotecas de terceiros populares, como Starscream.
Neste artigo, vamos analisar como integrar WebSocket no seu aplicativo Swift para iOS e macOS, escrever exemplos de código funcionais e considerar as melhores práticas.
1. Implementação nativa de WebSocket via URLSession
A partir do iOS 13 e macOS 10.15, a Apple oferece suporte nativo a WebSocket através da classe URLSessionWebSocketTask. Esta é a forma mais simples e recomendada, que não requer instalação de dependências de terceiros.
Criação e configuração da conexão
Primeiro, é necessário criar uma instância de URLSession e definir a configuração. Em seguida, montamos uma URL com o protocolo ws:// (ou wss:// para conexão segura) e criamos a tarefa WebSocket.
import Foundation
class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private let session: URLSession override init() { let config = URLSessionConfiguration.default self.session = URLSession(configuration: config, delegate: nil, delegateQueue: OperationQueue()) super.init() } func connect() { guard let url = URL(string: "wss://echo.websocket.org") else { return } webSocketTask = session.webSocketTask(with: url) webSocketTask?.resume() receiveMessage() } func disconnect() { webSocketTask?.cancel(with: .normalClosure, reason: nil) }}Envio e recebimento de mensagens
O WebSocket suporta o envio tanto de dados textuais (URLSessionWebSocketTask.Message.string) quanto binários (.data). Para receber mensagens, é necessário chamar recursivamente o método receive, pois ele processa apenas uma mensagem por vez.
extension WebSocketManager { func sendMessage(_ text: String) { let message = URLSessionWebSocketTask.Message.string(text) webSocketTask?.send(message) { error in if let error = error { print("Erro ao enviar: \\(error.localizedDescription)") } } } private func receiveMessage() { webSocketTask?.receive { [weak self] result in switch result { case .success(let message): switch message { case .string(let text): print("Mensagem de texto recebida: \\(text)") case .data(let data): print("Dados binários recebidos: \\(data.count) bytes") @unknown default: print("Tipo de mensagem desconhecido") } // Continua ouvindo recursivamente self?.receiveMessage() case .failure(let error): print("Erro ao receber: \\(error.localizedDescription)") } } }}Observe a chamada recursiva de receiveMessage() dentro do closure de sucesso — isso garante que seu aplicativo receberá continuamente novos dados.