الخيط الخلفي في Swift: دليل للمبتدئين والمحترفين

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

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

ابدأ الدورة

لماذا تعتبر الخيوط الخلفية كابوسًا لكل مطور iOS؟

\n\n

تخيل: أنت تكتب تطبيقًا لتحميل الصور من الإنترنت. كل شيء يعمل بشكل مثالي... حتى يضغط المستخدم على زر "تحميل". تتجمد الشاشة، ويبطئ التطبيق، وبعد بضع ثوانٍ يقوم iOS بقتل عمليتك. هل هذا مألوف؟

\n\n

المشكلة هي أن جميع العمليات يتم تنفيذها افتراضيًا على الخيط الرئيسي (main thread). والخيط الرئيسي مسؤول عن عرض واجهة المستخدم (UI) - إذا قمت بحظره بمهمة طويلة، ستتوقف الواجهة عن الاستجابة للمسات. الحل؟ استخدام الخيط الخلفي (background thread) في Swift.

\n\n

في هذه المقالة، سنتعلم كيفية العمل مع الخيوط الخلفية من خلال أمثلة عملية. ستتعرف على GCD وOperationQueue و async/await الجديد من Swift 5.5+. هيا بنا!

\n\n

ما هو الخيط (thread) في Swift؟

\n\n

الخيط هو عملية خفيفة تنفذ كود البرنامج. يحتوي تطبيق iOS على خيط رئيسي (main thread) والعديد من الخيوط الخلفية. الخيط الرئيسي يتعامل مع واجهة المستخدم: تحديث الشاشة، معالجة الإيماءات، الرسوم المتحركة. كل ما يتعلق بالواجهة يجب أن يحدث فقط على الخيط الرئيسي.

\n\n

الخيوط الخلفية (background threads) ضرورية من أجل:

\n
    \n
  • تحميل البيانات من الشبكة
  • \n
  • العمل مع الملفات (قراءة/كتابة)
  • \n
  • الحسابات المعقدة (معالجة الصور، التشفير)
  • \n
  • العمل مع قواعد البيانات
  • \n
\n\n

إذا حاولت تحديث واجهة المستخدم من خيط خلفي - سيتعطل التطبيق مع خطأ، أو سترى سلوكًا غريبًا للواجهة.

\n\n

GCD (Grand Central Dispatch) - الطريقة التقليدية

\n\n

Grand Central Dispatch (GCD) هي مكتبة منخفضة المستوى لإدارة الخيوط، مدمجة في iOS/macOS. تعمل من خلال قوائم الانتظار (queues): تضع المهمة في قائمة الانتظار، ويقرر النظام بنفسه على أي خيط ينفذها.

\n\n

DispatchQueue.main - الخيط الرئيسي

\n

إذا كنت بحاجة لتنفيذ كود على الخيط الرئيسي (على سبيل المثال، تحديث UILabel)، استخدم:

\n\n
DispatchQueue.main.async {\n    self.label.text = "تم التحميل!"\n}
\n\n

DispatchQueue.global() - الخيط الخلفي

\n

للمهام الخلفية، استخدم قائمة الانتظار العامة:

\n\n
DispatchQueue.global(qos: .background).async {\n    // عمل ثقيل\n    let imageData = try? Data(contentsOf: url)\n    \n    // نعود إلى الخيط الرئيسي لواجهة المستخدم\n    DispatchQueue.main.async {\n        self.imageView.image = UIImage(data: imageData!)\n    }\n}
\n\n

المعامل qos (جودة الخدمة) يحدد أولوية المهمة:

\n
    \n
  • .userInteractive - الأعلى، لواجهة المستخدم
  • \n
  • .userInitiated - المستخدم ينتظر النتيجة
  • \n
  • .utility - مهام طويلة (تحميل الملفات)
  • \n
  • .background - أولوية منخفضة (مزامنة، نسخ احتياطي)
  • \n
\n\n

OperationQueue - تحكم أكبر

\n\n

OperationQueue هي طبقة فوق GCD مع إمكانيات إضافية:

\n
    \n
  • إلغاء المهام
  • \n
  • التبعيات بين المهام
  • \n
  • الحد الأقصى لعدد الخيوط المتوازية
  • \n
\n\n

مثال لتحميل عدة صور:

\n\n
let queue = OperationQueue()\nqueue.maxConcurrentOperationCount = 2 // لا يزيد عن مهمتين في وقت واحد\n\nlet operation1 = BlockOperation {\n    // تحميل الصورة الأولى\n    sleep(2)\n    print("تم تحميل الصورة 1")\n}\n\nlet operation2 = BlockOperation {\n    // تحميل الصورة الثانية\n    sleep(3)\n    print("تم تحميل الصورة 2")\n}\n\n// operation2 ستبدأ فقط بعد انتهاء operation1\noperation2.addDependency(operation1)\n\nqueue.addOperations([operation1, operation2], waitUntilFinished: false)
\n\n

هذا مفيد عندما تحتاج لتنفيذ المهام بترتيب صارم أو مع قيود على الموارد.

\n\n

async/await الحديث (Swift 5.5+)

\n\n

بدءًا من Swift 5.5، Ap

المدونات

توصيات الكتب