العمل مع قوائم المهام في Swift: من النظرية إلى المشاريع الحقيقية
\nفي التطوير الحديث لنظامي iOS وmacOS، سرعة استجابة الواجهة هي عامل النجاح الرئيسي للتطبيق. في كل مرة تقوم فيها بعملية ثقيلة (تحميل صورة، تحليل JSON، العمل مع قاعدة بيانات) على الخيط الرئيسي، يرى المستخدم "تجمّد" الواجهة. الحل هو قوائم المهام. في هذه المقالة، سنستعرض ثلاثة مناهج رئيسية للعمل مع القوائم في Swift: GCD الكلاسيكي، وOperationQueue عالي المستوى، وasync/await الحديث. ستحصل على أمثلة جاهزة للاستخدام من الكود وستعرف أي نهج تختار لمهمة محددة.
\n\n1. Grand Central Dispatch (GCD): بداية سريعة مع DispatchQueue
\nGrand Central Dispatch هي مكتبة منخفضة المستوى لإدارة التنفيذ المتوازي للكود. وهي أساس تعدد المهام في Swift ولا تزال الأداة الأكثر أداءً للمهام الخلفية البسيطة.
\n\nالأنواع الرئيسية للقوائم:
\n- \n
main— قائمة تسلسلية للخيط الرئيسي (جميع تحديثات واجهة المستخدم هنا فقط). \n global(qos:)— قوائم متوازية بأولويات (userInteractive, userInitiated, utility, background). \n custom(label:)— قائمتك الخاصة (يمكن أن تكون تسلسلية أو متوازية). \n
مثال: تحميل صورة وتحديث واجهة المستخدم
\nimport UIKit\n\nclass ImageLoader {\n func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {\n DispatchQueue.global(qos: .userInitiated).async {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else {\n DispatchQueue.main.async {\n completion(nil)\n }\n return\n }\n DispatchQueue.main.async {\n completion(image)\n }\n }\n }\n}\n\nنصيحة عملية: استخدم دائمًا .userInitiated للمهام التي يتوقعها المستخدم فورًا (مثل فتح صورة). لمزامنة البيانات في الخلفية، استخدم .background.
2. OperationQueue: إدارة التبعيات وإلغاء المهام
\nعندما يصبح المنطق أكثر تعقيدًا (تحتاج إلى إلغاء مهمة، أو تحديد ترتيب التنفيذ، أو تقييد عدد العمليات المتوازية)، يأتي OperationQueue للإنقاذ. على عكس GCD، العمليات هي كائنات يمكن إعادة استخدامها والتحكم بها.
الإمكانيات الرئيسية:
\n- \n
- إلغاء المهام عبر
cancel(). \n - التبعيات (
addDependency) — المهمة B ستنفذ فقط بعد المهمة A. \n - التحكم في الحد الأقصى لعدد العمليات المتوازية (
maxConcurrentOperationCount). \n
مثال: تحميل عدة صور مع تقييد التوازي
\nimport UIKit\n\nclass BatchImageDownloader {\n private let queue: OperationQueue = {\n let q = OperationQueue()\n q.maxConcurrentOperationCount = 3 // لا يزيد عن 3 تحميلات في وقت واحد\n q.qualityOfService = .userInitiated\n return q\n }()\n \n func downloadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) {\n var images: [UIImage] = []\n let syncQueue = DispatchQueue(label: "sync.images")\n \n let finishOperation = BlockOperation {\n DispatchQueue.main.async {\n completion(images)\n }\n }\n \n for url in urls {\n let operation = BlockOperation {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else { return }\n syncQueue.async {\n images.append(image)\n }\n }\n