مقدمة في التزامن وتعدد الخيوط في Swift
يجب أن تكون التطبيقات الحديثة لنظامي iOS وmacOS سريعة وسريعة الاستجابة. لا ينبغي للمستخدم الانتظار حتى يتم تحميل صورة أو إجراء عملية حسابية معقدة. لهذا الغرض، توجد آليات التزامن وتعدد الخيوط في Swift. في هذه المقالة، سنشرح المفاهيم الأساسية، بدءًا من Grand Central Dispatch (GCD) الكلاسيكي وصولاً إلى async/await الحديث من Swift Concurrency.
التزامن (concurrency) هو قدرة البرنامج على تنفيذ مهام متعددة في وقت واحد، مع التبديل بينها. تعدد الخيوط (multithreading) هو أحد تطبيقات التزامن، حيث يتم تنفيذ المهام في خيوط مختلفة من نظام التشغيل. يوفر Swift أدوات قوية وآمنة للعمل مع هذه المفاهيم.
1. Grand Central Dispatch (GCD) — أساس تعدد الخيوط
Grand Central Dispatch (GCD) هي مكتبة منخفضة المستوى من Apple لإدارة التنفيذ المتوازي للكود. تعمل بناءً على قوائم الانتظار (dispatch queues).
أنواع قوائم الانتظار في GCD
- Serial Queue (قائمة انتظار تسلسلية) — يتم تنفيذ المهام واحدة تلو الأخرى بترتيب الإضافة.
- Concurrent Queue (قائمة انتظار متوازية) — يمكن تنفيذ المهام في وقت واحد على خيوط مختلفة.
- Main Queue (قائمة الانتظار الرئيسية) — تنفذ المهام على الخيط الرئيسي، مخصصة لتحديث واجهة المستخدم.
- Global Queues (قوائم الانتظار العالمية) — قوائم انتظار متوازية من النظام بأولويات مختلفة (QoS).
مثال: تنفيذ مهمة في الخلفية وتحديث واجهة المستخدم
import UIKit
class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView!
func loadImage(from url: URL) { // التبديل إلى قائمة انتظار الخلفية DispatchQueue.global(qos: .background).async { [weak self] in guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return } // العودة إلى الخيط الرئيسي لتحديث واجهة المستخدم DispatchQueue.main.async { self?.imageView.image = image } } }}في هذا المثال، نقوم بتنزيل الصورة في خيط الخلفية لتجنب حظر الواجهة، ثم نقوم بتحديث واجهة المستخدم على الخيط الرئيسي.
DispatchGroup لمزامنة المهام
يتيح DispatchGroup تتبع تنفيذ مجموعة من المهام غير المتزامنة وتنفيذ إجراء بعد اكتمالها.
let group = DispatchGroup()
group.enter()fetchData1 { result in print("تم الحصول على البيانات 1") group.leave()}
group.enter()fetchData2 { result in print("تم الحصول على البيانات 2") group.leave()}
group.notify(queue: .main) { print("تم تحميل جميع البيانات، نقوم بتحديث واجهة المستخدم")}2. OperationQueue — نهج موجه للكائنات
OperationQueue هي تجريد أعلى مستوى فوق GCD. تعمل مع كائنات Operation، التي تمثل وحدة عمل.
مزايا OperationQueue
- إمكانية إلغاء المهام (cancel).
- تعيين التبعيات بين العمليات (addDependency).
- مراقبة حالة العملية (isFinished, isExecuting, isCancelled).
- تكوين الحد الأقصى لعدد العمليات المتوازية.
مثال: تحميل عدة صور
import UIKit
class ImageLoader { private let queue = OperationQueue() func loadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) { var images: [UIImage] = [] let completionOperation = BlockOperation { DispatchQueue.main.async { completion(images) } } for url in urls { let o