مقدمة في التزامن وتعدد الخيوط في Swift
تتطلب تطبيقات iOS وmacOS الحديثة بشكل متزايد تنفيذ مهام متعددة في وقت واحد. سواء كان تحميل البيانات من الشبكة، أو معالجة الصور، أو العمليات الحسابية المعقدة — لا يمكن الاستغناء عن إدارة الخيوط بكفاءة. في Swift، تم تنفيذ التزامن وتعدد الخيوط على أعلى مستوى، مما يوفر للمطور أدوات قوية وآمنة.
في هذه المقالة، سنستعرض ثلاث طرق رئيسية: Grand Central Dispatch (GCD)، وOperationQueue، والكلمة المفتاحية الحديثة async/await التي ظهرت في Swift 5.5. ستتعلم كيفية الاختيار الصحيح بينها وتجنب الأخطاء الشائعة، مثل حالة السباق (race condition) والحظر المتبادل (deadlock).
Grand Central Dispatch (GCD) — كلاسيكيات تعدد الخيوط في Swift
Grand Central Dispatch (GCD) هي مكتبة منخفضة المستوى من Apple تدير مجموعة من الخيوط. لا يحتاج المطور إلى إنشاء الخيوط وتدميرها يدويًا — يقوم GCD بذلك تلقائيًا، موزعًا المهام على أنوية المعالج المتاحة.
قوائم الانتظار الرئيسية في GCD
يوجد في GCD نوعان من قوائم الانتظار: التسلسلية (serial) والمتوازية (concurrent). يتم تنفيذ المهام في قائمة الانتظار التسلسلية واحدة تلو الأخرى، بينما في المتوازية يمكن تشغيلها في وقت واحد.
// إنشاء قائمة انتظار تسلسليةlet serialQueue = DispatchQueue(label: "com.example.serial")serialQueue.async { print("المهمة 1")}serialQueue.async { print("المهمة 2")}
// إنشاء قائمة انتظار متوازيةlet concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)concurrentQueue.async { print("المهمة المتوازية A")}concurrentQueue.async { print("المهمة المتوازية B")}قوائم الانتظار العالمية وجودة الخدمة (QoS)
يوفر GCD قوائم انتظار عالمية جاهزة بأولويات مختلفة (Quality of Service). استخدمها عندما لا تحتاج إلى إنشاء قائمة انتظار خاصة بك:
.userInteractive— لتحديثات واجهة المستخدم (أعلى أولوية).userInitiated— للمهام التي بدأها المستخدم.utility— للعمليات الخلفية الطويلة.background— للمهام غير الحرجة من حيث الوقت
DispatchQueue.global(qos: .userInitiated).async { // عمل ثقيل let result = performComplexCalculation() DispatchQueue.main.async { // العودة إلى الخيط الرئيسي لتحديث واجهة المستخدم self.updateUI(with: result) }}هام: قم دائمًا بتحديث واجهة المستخدم فقط على الخيط الرئيسي (DispatchQueue.main). تجاهل هذه القاعدة يؤدي إلى أعطال غير متوقعة في التطبيق.
OperationQueue — إدارة تبعيات المهام
إذا كان GCD هو "السكين السويسري"، فإن OperationQueue هو جدولة متكاملة مع إمكانية الإلغاء، وتحديد الأولويات، وإنشاء تبعيات بين العمليات. كل عملية هي نسخة من الفئة Operation (أو فئتها الفرعية BlockOperation).
إنشاء وتنفيذ العمليات
let operationQueue = OperationQueue()operationQueue.maxConcurrentOperationCount = 2 // تحديد عدد العمليات المتوازية
let operation1 = BlockOperation { print("العملية 1")}let operation2 = BlockOperation { print("العملية 2")}
// إضافة تبعية: ستبدأ العملية 2 فقط بعد انتهاء العملية 1operation2.addDependency(operation1)
operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)الإلغاء والأولويات
على عكس GCD، يسمح OperationQueue بإلغاء عملية محددة أو قائمة الانتظار بأكملها:
// إلغاء عملية واحدةoperation1.cancel()
// إلغاء قائمة الانتظار بأكملهاoperationQueue.cancelAllOperations()
// تعيين الأولويةoperation1.