لماذا يحتاج تطبيق Swift الخاص بك إلى هندسة معمارية قائمة على الأحداث (event-driven architecture)؟
تخيل أنك قائد أوركسترا. كل موسيقي ينتظر دوره ليدخل في اللحظة المناسبة. إذا عزف عازفو الكمان جميعًا في وقت واحد، فسينتج عن ذلك فوضى. بنفس الطريقة تقريبًا تعمل الهندسة المعمارية القائمة على الأحداث (event-driven architecture) بلغة Swift: كل وحدة (module) تتفاعل فقط مع أحداث معينة، ولا تقوم بسحب الوحدات الأخرى بشكل مباشر.
عندما واجهت لأول مرة البرمجة الموجهة بالأحداث (event-driven programming) بلغة Swift في مشروع تجاري، أدركت مدى قوة هذه الأداة. تطبيق لتوصيل الطعام: المستخدم ضغط على زر "اطلب" - هذا حدث. تم تحديث سلة التسوق - حدث. وصل إشعار (push) مع معلومات الساعي - حدث. كل وحدة (واجهة المستخدم، الشبكة، قاعدة البيانات المحلية) تشترك ببساطة في الأحداث التي تحتاجها وتعمل بشكل مستقل. هذه هي الهندسة المعمارية القائمة على الأحداث (event-driven architecture).
في هذه المقالة، سنتناول ثلاثة طرق لتنفيذ هندسة الأحداث (event architecture) بلغة Swift: المفوضون (Delegates) التقليديون، و NotificationCenter، وناقل الأحداث المخصص (custom event bus). سترى كودًا حقيقيًا، وستفهم متى تستخدم أيًا منها، وستتمكن من تطبيقها فورًا في مشروعك. هيا بنا!
أساسيات النهج القائم على الأحداث (event-driven approach) بلغة Swift
ما هو الحدث (Event) في سياق Swift؟
الحدث هو إشارة إلى أن شيئًا ما قد حدث. يمكن أن يكون:
- إدخال المستخدم (تم الضغط على زر، تم تغيير نص)
- تغيير في البيانات (وصلت بيانات من الخادم، تم تحديث قاعدة البيانات)
- إشعارات النظام (التطبيق انتقل إلى الخلفية، ظهرت لوحة المفاتيح)
المبدأ الرئيسي لـ الهندسة المعمارية القائمة على الأحداث (event-driven architecture) بلغة Swift هو الاقتران الضعيف (loose coupling). مرسل الحدث لا يعرف من سيعالجه. المستقبل لا يعرف من أرسله. يتواصلون عبر ناقل الأحداث - وهذا يجعل الكود مرنًا وقابلاً للاختبار.
نمط Observer - أساس الأحداث
نمط Observer بلغة Swift هو أساس أي نظام قائم على الأحداث. لدينا كائن ناشر (Publisher) واحد والعديد من المشتركين (Subscribers). عندما يغير الناشر حالته، يقوم بإخطار جميع المشتركين.
في Swift، هناك عدة آليات مدمجة لذلك:
NotificationCenter- ناقل أحداث عالمي في iOS SDK- المفوضون (Delegates) - واحد لواحد، ولكن مع التحكم
Combine- إطار عمل تفاعلي من Apple (iOS 13+)- التطبيقات المخصصة (Custom implementations) - تحكم كامل في السلوك
دعنا نتناول كل نهج مع أمثلة.
الطريقة 1. المفوضون (Delegates): الكلاسيكية
المفوضون (Delegates) في Swift هي أبسط طريقة لتنفيذ حدث. وهي مناسبة للعلاقات "واحد لواحد"، عندما يخبر كائن واحد كائنًا آخر عن حالته.
مثال: تخيل أن لدينا محمل صور (Image Loader) يجب أن يخبر وحدة التحكم (Controller) عند اكتمال التحميل.
// 1. تعريف بروتوكول المفوضprotocol ImageLoaderDelegate: AnyObject { func imageLoader(_ loader: ImageLoader, didLoad image: UIImage) func imageLoader(_ loader: ImageLoader, didFailWith error: Error)}
// 2. فئة الناشرclass ImageLoader { weak var delegate: ImageLoaderDelegate?
func loadImage(from url: URL) { URLSession.shared.dataTask(with: url) { [weak self] data, _, error in DispatchQueue.main.async { if let error = error { self?.delegate?.imageLoader(self!, didFailWith: error) } else if let data = data, let image = UIImage(data: data) { self?.delegate?.imageLoader(self!, didLoad: image) } } }.resume() }}
// 3. وحدة التحكم المشتركةclass ViewController: UIViewController, ImageLoaderDelegate { let loader = ImageLoader() @IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() { super.viewDidLoad() lo