Rate Limiting em Swift: Limitação de Frequência de Requisições para iOS e macOS

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

Rate Limiting em Swift: Guia Completo para Aplicativos iOS e macOS

\n\n

Rate limiting (limitação de frequência de requisições) é um mecanismo criticamente importante para a operação estável de aplicativos móveis e desktop. No ecossistema Swift (iOS/macOS), esta abordagem permite controlar o número de chamadas de API, operações de entrada/saída ou quaisquer ações repetitivas por unidade de tempo. Sem rate limiting, seu aplicativo corre o risco de ser bloqueado pelo servidor, desperdiçar bateria com tentativas infinitas ou criar carga excessiva na rede.

\n\n

Por que a limitação de frequência de requisições é necessária em Swift?

\n\n
    \n
  • Proteção contra exceder limites de API — muitos servidores (ex.: GitHub, Twitter, Stripe) estabelecem cotas rigorosas para o número de requisições por minuto/hora.
  • \n
  • Otimização de desempenho — prevenção de uma "tempestade" de chamadas durante rolagem rápida ou animações.
  • \n
  • Economia de tráfego e bateria — especialmente relevante para dispositivos móveis.
  • \n
  • Conformidade com as políticas da App Store — requisições em segundo plano excessivas podem levar à rejeição do aplicativo.
  • \n
\n\n

Abordagens Principais para Implementar Rate Limiting em Swift

\n\n

Vamos considerar três padrões básicos que podem ser implementados sem bibliotecas de terceiros:

\n\n

1. Token Bucket (Balde de Tokens)

\n

Algoritmo clássico onde "tokens" são adicionados a uma taxa fixa. Cada requisição consome um token. Se os tokens acabarem, a requisição é rejeitada.

\n\n
import Foundation\n\nfinal class TokenBucket {\n    private let capacity: Int\n    private var tokens: Int\n    private let refillRate: Double // tokens por segundo\n    private var lastRefill: Date\n    private let queue = DispatchQueue(label: "token.bucket.queue")\n    \n    init(capacity: Int, refillRate: Double) {\n        self.capacity = capacity\n        self.tokens = capacity\n        self.refillRate = refillRate\n        self.lastRefill = Date()\n    }\n    \n    func tryConsume() -> Bool {\n        queue.sync {\n            refill()\n            if tokens > 0 {\n                tokens -= 1\n                return true\n            }\n            return false\n        }\n    }\n    \n    private func refill() {\n        let now = Date()\n        let elapsed = now.timeIntervalSince(lastRefill)\n        let newTokens = Int(elapsed * refillRate)\n        if newTokens > 0 {\n            tokens = min(capacity, tokens + newTokens)\n            lastRefill = now\n        }\n    }\n}\n\n// Exemplo de uso\nlet limiter = TokenBucket(capacity: 10, refillRate: 2.0) // 10 requisições, 2 por segundo\nif limiter.tryConsume() {\n    print("✅ Requisição permitida")\n} else {\n    print("⛔️ Limite excedido, aguarde")\n}
\n\n

2. Algoritmo de Janela Deslizante (Sliding Window)

\n

Armazena os timestamps das últimas N requisições bem-sucedidas. Se a janela estiver cheia, bloqueia novas chamadas.

\n\n
final class SlidingWindowLimiter {\n    private let maxRequests: Int\n    private let windowDuration: TimeInterval\n    private var timestamps: [Date] = []\n    private let queue = DispatchQueue(label: "sliding.window.queue")\n    \n    init(maxRequests: Int, windowDuration: TimeInterval = 60) {\n        self.maxRequests = maxRequests\n        self.windowDuration = windowDuration\n    }\n    \n    func canProceed() -> Bool {\n        queue.sync {\n            let now = Date()\n            // Remove timestamps antigos\n            timestamps.removeAll { now.timeIntervalSince($0) > windowDuration }\n            \n            if timestamps.count < maxRequests {\n                timestamps.append(now)\n                return true\n            }\n            return false\n        }\n    }\n}\n\n// Exemplo: no máximo 5 requisições em 10 segundos\nlet windowLimiter = SlidingWindowLimiter(maxRequests: 5, windowDuration: 10)
\n\n

3. Throttling com DispatchQueue

\n

Utiliza mecanismos integrados do GCD para atraso forçado

Recommendations