مقدمة: لماذا يعتبر WebSocket مهمًا لمطور Swift
في تطوير التطبيقات الحديثة للهواتف المحمولة وأجهزة سطح المكتب، اعتاد المستخدمون على التحديثات الفورية: تحديث خلاصة الأخبار دون إعادة تحميل، تغير حالة المحادث في الدردشة في الوقت الفعلي، ووصول أسعار الأسهم بتأخير بالمللي ثانية. بروتوكول HTTP التقليدي بنموذج الطلب والاستجابة غير فعال لمثل هذه المهام - فهو يخلق حملاً زائداً على الخادم وبطارية الجهاز.
يأتي بروتوكول WebSocket للمساعدة. فهو ينشئ اتصالاً ثنائي الاتجاه دائماً بين العميل (تطبيق iOS/macOS بلغة Swift) والخادم. في هذه المقالة، سنشرح طريقتين رئيسيتين للعمل مع WebSocket في Swift: الطريقة الأصلية URLSessionWebSocketTask (iOS 13+ / macOS 10.15+) والمكتبة الخارجية الشهيرة Starscream. ستتعلم كيفية إنشاء دردشة في الوقت الفعلي، وإعداد إعادة الاتصال التلقائي، ومعالجة الأخطاء.
أساسيات WebSocket في Swift: URLSessionWebSocketTask
بدءاً من iOS 13 و macOS Catalina، وفرت Apple دعماً مدمجاً لـ WebSocket من خلال الفئة URLSessionWebSocketTask. هذه طريقة بسيطة وآمنة لا تتطلب تثبيت تبعيات إضافية.
إنشاء وتهيئة الاتصال
للبدء، سننشئ نسخة من URLSession ونحدد التهيئة. لاحظ: للعمل مع WebSocket، يجب استخدام البروتوكول wss:// (اتصال آمن) أو ws:// (اتصال غير آمن، للتطوير فقط).
import Foundation
class WebSocketManager: NSObject {
private var webSocketTask: URLSessionWebSocketTask?
private let session: URLSession
override init() {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
config.waitsForConnectivity = true
self.session = URLSession(configuration: config, delegate: nil, delegateQueue: OperationQueue())
super.init()
}
func connect() {
guard let url = URL(string: "wss://echo.websocket.org") else { return }
webSocketTask = session.webSocketTask(with: url)
webSocketTask?.resume()
print("تم إنشاء اتصال WebSocket")
receiveMessage()
}
}
إرسال واستقبال الرسائل
يدعم WebSocket نوعين من الرسائل: نصية (String) وثنائية (Data). لننظر إلى الإرسال:
func sendMessage(_ text: String) {
let message = URLSessionWebSocketTask.Message.string(text)
webSocketTask?.send(message) { error in
if let error = error {
print("خطأ في الإرسال: \\(error.localizedDescription)")
} else {
print("تم إرسال الرسالة: \\(text)")
}
}
}
لاستقبال الرسائل، يجب تنفيذ استدعاء متكرر للطريقة receive:
private func receiveMessage() {
webSocketTask?.receive { [weak self] result in
switch result {
case .success(let message):
switch message {
case .string(let text):
print("تم استقبال رسالة نصية: \\(text)")
case .data(let data):
print("تم استقبال بيانات ثنائية: \\(data.count) بايت")
@unknown default:
break
}
// نستمر في الاستماع للرسائل التالية
self?.receiveMessage()
case .failure(let error):
print("خطأ في الاستقبال: \\(error.localizedDescription)")
// هنا يمكن تنفيذ إعادة الاتصال
}
}
}
إغلاق الاتصال ومعالجة الأخطاء
إنهاء العمل مع WebSocket بشكل صحيح هو جزء مهم من تطبيق الإنتاج:
func disconnect() {
let closeCode = URLSessionWebSocketTask.CloseCode.normalClosure
webSocketTask?.cancel(with: closeCode, reason: nil)
p