تحديد معدل الطلبات في Swift: الحد من تكرار الطلبات لنظامي iOS و macOS

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تحديد معدل الطلبات في Swift: دليل شامل لتطبيقات iOS و macOS

\n\n

تحديد معدل الطلبات (Rate limiting) هو آلية بالغة الأهمية لضمان استقرار عمل تطبيقات الهواتف المحمولة وأجهزة الكمبيوتر المكتبية. في نظام Swift البيئي (iOS/macOS)، يسمح هذا الأسلوب بالتحكم في عدد استدعاءات API، وعمليات الإدخال/الإخراج، أو أي إجراءات متكررة في وحدة زمنية. بدون تحديد معدل الطلبات، قد يتعرض تطبيقك لخطر الحظر من قبل الخادم، أو استنزاف طاقة البطارية في إعادة المحاولات اللانهائية، أو إنشاء حمل زائد على الشبكة.

\n\n

لماذا نحتاج إلى الحد من تكرار الطلبات في Swift؟

\n\n
    \n
  • الحماية من تجاوز حدود API — تفرض العديد من الخوادم (مثل GitHub، Twitter، Stripe) حصصًا صارمة على عدد الطلبات في الدقيقة/الساعة.
  • \n
  • تحسين الأداء — منع "عاصفة" الاستدعاءات عند التمرير السريع أو الرسوم المتحركة.
  • \n
  • توفير البيانات والبطارية — خاصةً بالنسبة للأجهزة المحمولة.
  • \n
  • الامتثال لسياسات App Store — قد تؤدي الطلبات الخلفية المفرطة إلى رفض التطبيق.
  • \n
\n\n

الأساليب الأساسية لتطبيق تحديد معدل الطلبات في Swift

\n\n

دعنا نستعرض ثلاثة أنماط أساسية يمكن تنفيذها دون الحاجة إلى مكتبات خارجية:

\n\n

1. دلو الرموز (Token Bucket)

\n

خوارزمية كلاسيكية حيث تتم إضافة "الرموز" بمعدل ثابت. يستهلك كل طلب رمزًا واحدًا. إذا نفدت الرموز، يتم رفض الطلب.

\n\n
import Foundation\n\nfinal class TokenBucket {\n    private let capacity: Int\n    private var tokens: Int\n    private let refillRate: Double // رمز في الثانية\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// مثال على الاستخدام\nlet limiter = TokenBucket(capacity: 10, refillRate: 2.0) // 10 طلبات، 2 في الثانية\nif limiter.tryConsume() {\n    print("✅ الطلب مسموح به")\n} else {\n    print("⛔️ تم تجاوز الحد، انتظر")\n}
\n\n

2. خوارزمية النافذة المنزلقة (Sliding Window)

\n

يتذكر الطوابع الزمنية لآخر N من الطلبات الناجحة. إذا كانت النافذة ممتلئة، يتم حظر الاستدعاءات الجديدة.

\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            // إزالة الطوابع الزمنية القديمة\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// مثال: لا يزيد عن 5 طلبات في 10 ثوانٍ\nlet windowLimiter = SlidingWindowLimiter(maxRequests: 5, windowDuration: 10)
\n\n

3. الخنق (Throttling) باستخدام DispatchQueue

\n

يستخدم آليات GCD المدمجة لتأخير إجباري

توصيات