Long Polling vs WebSocket em Swift: o que escolher para iOS em 2025

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: o eterno dilema do desenvolvedor iOS

\n

Imagine: você está criando um aplicativo de mensagens ou de bolsa de valores. O usuário espera notificações em tempo real, e você se depara com a escolha — Long Polling ou WebSocket? Em Swift, ambas as abordagens são viáveis, mas cada uma com suas nuances. Neste artigo, não vamos apenas listar prós e contras, mas analisar exemplos reais de código, desempenho, impacto na bateria e fornecer um algoritmo claro de escolha. Vamos lá!

\n\n

O que é Long Polling em Swift? (e por que não é uma "requisição eterna")

\n

Long Polling é uma requisição HTTP clássica que o servidor não fecha imediatamente, mas mantém aberta até que um novo evento ocorra ou o tempo limite expire. Em Swift, isso é implementado através de URLSession com um timeoutIntervalForRequest personalizado.

\n

Muitos confundem Long Polling com polling comum (quando o cliente consulta o servidor a cada 5 segundos). A diferença é que no Long Polling o próprio servidor "empurra" os dados assim que eles aparecem, e o cliente envia imediatamente uma nova requisição após receber a resposta.

\n\n

Exemplo de Long Polling em Swift com async/await

\n
import Foundation\n\nclass LongPollingClient {\n    private let session: URLSession\n    private let baseURL = URL(string: "https://api.pythonlib.ru/events")!\n    private var isPolling = false\n    \n    init() {\n        let config = URLSessionConfiguration.default\n        config.timeoutIntervalForRequest = 60 // Tempo limite longo\n        config.waitsForConnectivity = true\n        self.session = URLSession(configuration: config)\n    }\n    \n    func startPolling() async {\n        isPolling = true\n        while isPolling {\n            do {\n                let (data, response) = try await session.data(from: baseURL)\n                guard let httpResponse = response as? HTTPURLResponse,\n                      httpResponse.statusCode == 200 else {\n                    continue\n                }\n                // Processamento dos dados recebidos\n                if let events = try? JSONDecoder().decode([Event].self, from: data) {\n                    await handleEvents(events)\n                }\n            } catch {\n                // Se for tempo limite, apenas inicia um novo ciclo\n                if let urlError = error as? URLError, \n                   urlError.code == .timedOut {\n                    continue\n                }\n                // Outros erros — registramos e esperamos\n                print("Polling error: \\(error.localizedDescription)")\n                try? await Task.sleep(nanoseconds: 5_000_000_000)\n            }\n        }\n    }\n    \n    func stopPolling() {\n        isPolling = false\n    }\n    \n    private func handleEvents(_ events: [Event]) async {\n        // Atualizamos a UI na thread principal\n        await MainActor.run {\n            NotificationCenter.default.post(name: .newEvents, object: events)\n        }\n    }\n}
\n

Importante: não se esqueça do Task.sleep em caso de erros, para não sobrecarregar o servidor com reconexões infinitas. No pythonlib.ru, testamos essa abordagem com uma carga de 10 mil clientes — o servidor se mantém bem, mas a latência aumenta.

\n\n

WebSocket em Swift: poder nativo ou Starscream?

\n

Com o iOS 13, a Apple adicionou suporte nativo a WebSocket através de URLSessionWebSocketTask. Isso significa que você pode esquecer as bibliotecas de terceiros, embora o Starscream continue sendo uma escolha popular para projetos que precisam de suporte a iOS antigo (12 ou inferior).

\n\n

Exemplo de WebSocket nativo em Swift (iOS 13+)

\n
import Foundation\n\nclass WebSocketManager: NSObject, URLSessionWebSocketDelegate {\n    private var webSocket: URLSessionWebSocketTask?\n    private let session: URLSession\n    \n    override init() {\n        let config = URLSessionConfiguration.default\n        config.timeoutIntervalForRequest = 60\n        self.session = URLSession(configuration: config)\n                

Blogs

Book Recommendations