Swift中的速率限制:iOS和macOS的请求频率限制

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift中的速率限制:iOS和macOS应用完整指南



速率限制(请求频率限制)是确保移动和桌面应用稳定运行的关键机制。在Swift(iOS/macOS)生态系统中,这种方法可以控制单位时间内API调用、I/O操作或任何重复操作的数量。如果没有速率限制,您的应用可能会被服务器封锁,因无限重试而耗尽电池电量,或对网络造成过大负载。



为什么需要在Swift中限制请求频率?



  • 防止超出API限制 — 许多服务器(例如GitHub、Twitter、Stripe)对每分钟/小时的请求数量设有严格配额。
  • 优化性能 — 防止快速滚动或动画时出现调用“风暴”。
  • 节省流量和电池 — 对移动设备尤为重要。
  • 遵守App Store政策 — 过多的后台请求可能导致应用被拒绝。


Swift中实现速率限制的主要方法



让我们看看三种无需第三方库即可实现的基本模式:



1. 令牌桶(Token Bucket)

经典算法,其中“令牌”以固定速率添加。每个请求消耗一个令牌。如果令牌用完,请求将被拒绝。



import Foundation

final class TokenBucket { private let capacity: Int private var tokens: Int private let refillRate: Double // 每秒令牌数 private var lastRefill: Date private let queue = DispatchQueue(label: "token.bucket.queue") init(capacity: Int, refillRate: Double) { self.capacity = capacity self.tokens = capacity self.refillRate = refillRate self.lastRefill = Date() } func tryConsume() -> Bool { queue.sync { refill() if tokens > 0 { tokens -= 1 return true } return false } } private func refill() { let now = Date() let elapsed = now.timeIntervalSince(lastRefill) let newTokens = Int(elapsed * refillRate) if newTokens > 0 { tokens = min(capacity, tokens + newTokens) lastRefill = now } }}

// 使用示例let limiter = TokenBucket(capacity: 10, refillRate: 2.0) // 10个请求,每秒2个if limiter.tryConsume() { print("✅ 请求已允许")} else { print("⛔️ 超出限制,请等待")}


2. 滑动窗口算法(Sliding Window)

记录最近N个成功请求的时间戳。如果窗口已满,则阻止新调用。



final class SlidingWindowLimiter {    private let maxRequests: Int    private let windowDuration: TimeInterval    private var timestamps: [Date] = []    private let queue = DispatchQueue(label: "sliding.window.queue")        init(maxRequests: Int, windowDuration: TimeInterval = 60) {        self.maxRequests = maxRequests        self.windowDuration = windowDuration    }        func canProceed() -> Bool {        queue.sync {            let now = Date()            // 移除过期的时间戳            timestamps.removeAll { now.timeIntervalSince($0) > windowDuration }                        if timestamps.count < maxRequests {                timestamps.append(now)                return true            }            return false        }    }}

// 示例:10秒内不超过5个请求let windowLimiter = SlidingWindowLimiter(maxRequests: 5, windowDuration: 10)


3. 使用DispatchQueue进行节流

利用GCD内置机制强制延迟

推荐