Long Polling مقابل WebSocket في Swift: أيهما تختار لتطبيقات iOS في 2025

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

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

ابدأ الدورة

مقدمة: المعضلة الأبدية لمطور iOS

\n

تخيل: أنت تكتب تطبيق مراسلة أو تطبيق تداول. المستخدم ينتظر الإشعارات في الوقت الفعلي، وأنت أمام خيار - Long Polling أم WebSocket؟ في Swift، كلا النهجين لهما ما يبررهما، ولكن لكل منهما تفاصيله الخاصة. في هذه المقالة، لن نكتفي بسرد الإيجابيات والسلبيات، بل سنحلل أمثلة كود حقيقية، الأداء، التأثير على البطارية، وسنقدم خوارزمية اختيار واضحة. هيا بنا!

\n\n

ما هو Long Polling في Swift؟ (ولماذا ليس "طلبًا أبديًا")

\n

Long Polling هو طلب HTTP تقليدي لا يغلقه الخادم فورًا، بل يبقيه مفتوحًا حتى يظهر حدث جديد أو تنتهي المهلة. في Swift، يتم تنفيذ ذلك عبر URLSession مع timeoutIntervalForRequest مخصص.

\n

كثيرون يخلطون بين Long Polling والاستقصاء العادي (عندما يطلب العميل من الخادم كل 5 ثوانٍ). الفرق هو أنه في Long Polling، الخادم نفسه "يدفع" البيانات بمجرد ظهورها، بينما يرسل العميل طلبًا جديدًا فور تلقي الرد.

\n\n

مثال Long Polling في Swift باستخدام 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 // مهلة طويلة\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                // معالجة البيانات المستلمة\n                if let events = try? JSONDecoder().decode([Event].self, from: data) {\n                    await handleEvents(events)\n                }\n            } catch {\n                // إذا انتهت المهلة - ابدأ دورة جديدة ببساطة\n                if let urlError = error as? URLError, \n                   urlError.code == .timedOut {\n                    continue\n                }\n                // أخطاء أخرى - سجلها وانتظر\n                print("خطأ في الاستقصاء: \\(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        // تحديث واجهة المستخدم على الخيط الرئيسي\n        await MainActor.run {\n            NotificationCenter.default.post(name: .newEvents, object: events)\n        }\n    }\n}
\n

هام: لا تنسَ استخدام Task.sleep عند حدوث أخطاء، لتجنب إغراق الخادم بمحاولات إعادة اتصال لا نهائية. على pythonlib.ru اختبرنا هذا النهج تحت حمولة 10 آلاف عميل - الخادم صمد بشكل جيد، لكن زمن الاستجابة زاد.

\n\n

WebSocket في Swift: القوة الأصلية أم Starscream؟

\n

منذ iOS 13، أضافت Apple دعمًا أصليًا لـ WebSocket عبر URLSessionWebSocketTask. هذا يعني أنه يمكنك نسيان المكتبات الخارجية، على الرغم من أن Starscream لا يزال خيارًا شائعًا للمشاريع التي تحتاج دعم iOS القديم (12 وما دونه).

\n\n

مثال WebSocket أصلي في 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                

المدونات

توصيات الكتب