مقدمة في البرمجة غير المتزامنة في Swift
تتطلب التطبيقات الحديثة لنظامي iOS وmacOS استجابة عالية وأداءً ممتازًا. تتيح البرمجة غير المتزامنة في Swift تنفيذ العمليات الطويلة (طلبات الشبكة، العمل مع الملفات، معالجة البيانات) دون حظر الخيط الرئيسي (Main Thread). بدءًا من إصدار Swift 5.5، قدمت Apple نموذجًا قويًا يُسمى Swift Concurrency، يعتمد على الكلمات المفتاحية async و await، والذي يبسط بشكل كبير كتابة الكود غير المتزامن مقارنةً بالإغلاقات التقليدية (completion handlers) أو DispatchQueue.
في هذا الدليل، سنقوم بتحليل جميع المفاهيم الأساسية بالتفصيل: من أساسيات async/await إلى المواضيع المتقدمة مثل Actors و Task Groups. ستتعلم كيفية كتابة كود غير متزامن آمن وقابل للقراءة وفعال لمشاريعك في Swift.
أساسيات async/await في Swift
الكلمتان المفتاحيتان async و await هما جوهر Swift Concurrency. تسمحان بكتابة كود غير متزامن يبدو وكأنه متزامن، مما يحسن بشكل كبير قابلية القراءة ويقلل من عدد الأخطاء.
إعلان دالة غير متزامنة
لإعلان دالة على أنها غير متزامنة، أضف الكلمة المفتاحية async بعد قائمة المعاملات، ولكن قبل نوع الإرجاع. يمكن لهذه الدالة أن توقف تنفيذها مؤقتًا.
func fetchUserData(from url: URL) async throws -> Data { let (data, response) = try await URLSession.shared.data(from: url) // التحقق من حالة HTTP guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw URLError(.badServerResponse) } return data}استدعاء دالة غير متزامنة باستخدام await
لاستدعاء دالة غير متزامنة، تُستخدم الكلمة المفتاحية await. تشير إلى أن الكود الحالي قد يتوقف مؤقتًا عند هذه النقطة حتى يتم الحصول على النتيجة.
func loadProfile() async { let url = URL(string: "https://api.example.com/user/profile")! do { let data = try await fetchUserData(from: url) // معالجة البيانات (مثل فك تشفير JSON) print("تم استلام البيانات: \\(data.count) بايت") } catch { print("خطأ في تحميل الملف الشخصي: \\(error.localizedDescription)") }}Async let للمهام المتوازية
إذا كنت بحاجة إلى تنفيذ عدة عمليات غير متزامنة مستقلة في وقت واحد، استخدم البناء async let. يتيح ذلك تشغيل المهام بالتوازي وانتظار جميع النتائج.
func loadDashboardData() async -> Dashboard { async let user = fetchUserData(from: URL(string: "https://api.example.com/user")!) async let posts = fetchUserData(from: URL(string: "https://api.example.com/posts")!) async let notifications = fetchUserData(from: URL(string: "https://api.example.com/notifications")!)
// انتظار جميع النتائج let (userData, postsData, notifData) = await (try user, try posts, try notifications) return Dashboard(user: userData, posts: postsData, notifications: notifData)}Task و Structured Concurrency
يعتمد Swift Concurrency على مفهوم Structured Concurrency. وهذا يعني أن كل مهمة غير متزامنة لها عمر محدد بوضوح وعلاقة أبوية. اللبنة الأساسية هي Task.
إنشاء مهمة جديدة
يقوم Task بإنشاء وحدة عمل غير متزامنة جديدة. يمكنك إنشاء مهمة في سياق متزامن (مثل داخل viewDidLoad).
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // إنشاء مهمة جديدة لتنفيذ عمل غير متزامن Task { let data = try await fetchUserData(from: URL(string: "https://