عميل HTTP بلغة Swift: إجراء الطلبات بشكل صحيح — المستوى المتقدم

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

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

ابدأ الدورة

مقدمة: من طلبات GET الأساسية إلى عميل HTTP الصناعي

طلب HTTP القياسي بلغة Swift هو ثلاثة أسطر من الكود باستخدام URLSession.shared.dataTask. ولكن في المشاريع الحقيقية (تحميل الملفات، المصادقة باستخدام الرموز، التخزين المؤقت، إعادة المحاولة) هذا غير كافٍ. في هذه المقالة، سنستعرض التقنيات المتقدمة لإنشاء عميل HTTP بلغة Swift لتطبيقات iOS وmacOS: البروتوكولات المخصصة، إدارة الجلسات، تعدد المهام عبر async/await وCombine، بالإضافة إلى معالجة الأخطاء الموثوقة. المادة موجهة للمطورين الذين لديهم معرفة أساسية بـ URLSession.



هندسة عميل HTTP المتقدم

العميل الصناعي ليس مجرد دالة طلب، بل هو طبقة تجريد. سنقسمه إلى ثلاثة مستويات:

  • طبقة النقل (Transport Layer) — العمل منخفض المستوى مع URLSession، إدارة التهيئة.
  • طبقة الخدمة (Service Layer) — التسلسل/إلغاء التسلسل، معالجة رموز الحالة، إعادة المحاولة.
  • طبقة التطبيق (Application Layer) — منطق الأعمال، التخزين المؤقت، المصادقة.

سنبدأ بتخصيص طبقة النقل عبر URLProtocol.



1. URLProtocol مخصص لاعتراض وتعديل الطلبات

URLProtocol هو آلية قوية لاعتراض جميع طلبات الشبكة في التطبيق. يمكن استخدامه لإضافة التسجيل، توقيع الطلبات أو بيانات وهمية للاختبار.

import Foundation

class LoggingProtocol: URLProtocol { override class func canInit(with request: URLRequest) -> Bool { // اعتراض جميع طلبات HTTP/HTTPS return request.url?.scheme == "http" || request.url?.scheme == "https" }

override class func canonicalRequest(for request: URLRequest) -> URLRequest { return request }

override func startLoading() { print("📤 الطلب: \\(request.httpMethod ?? "GET") \\(request.url?.absoluteString ?? "")") print("📦 الرؤوس: \\(request.allHTTPHeaderFields ?? [:])")

let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in guard let self = self else { return } if let error = error { print("❌ خطأ: \\(error.localizedDescription)") self.client?.urlProtocol(self, didFailWithError: error) } else if let data = data, let response = response { print("✅ الرد: \\(response.expectedContentLength) بايت") self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .allowed) self.client?.urlProtocol(self, didLoad: data) } self.client?.urlProtocolDidFinishLoading(self) } task.resume() }

override func stopLoading() { // لا نفعل شيئًا، المهمة تنتهي بنفسها }}

// تسجيل البروتوكولURLProtocol.registerClass(LoggingProtocol.self)let config = URLSessionConfiguration.defaultconfig.protocolClasses = [LoggingProtocol.self]let session = URLSession(configuration: config)

الآن جميع الطلبات عبر هذه الجلسة سيتم تسجيلها. وبالمثل، يمكن إضافة رمز Bearer تلقائيًا أو معالجة حالة 401.



2. إدارة الجلسات: تهيئة مخصصة وتعدد المهام

استخدم URLSessionConfiguration مختلفة لأغراض مختلفة: .default للطلبات العادية، .ephemeral للبيانات الخاصة (بدون تخزين مؤقت وملفات تعريف الارتباط)، .background للتحميل في الخلفية.

let backgroundConfig = URLSessionConfiguration.background(withIdentifier: "com.pythonlib.background")backgroundConfig.isDiscretionary = truebackgroundConfig.sessionSendsLaunchEvents = truelet backgroundSession = URLSession(configuration: backgroundConfig, delegate: self, delegateQueue: nil)

لتعدد المهام، استخدم async/await (Swift 5.5+):

func performRequest(url: URL) async throws -> Data {    let (data, response)                

المدونات

توصيات الكتب