willSet و didSet في Swift: ما هما، التركيب وكيفية عمل المراقبين

المؤلف: IT Sectr نُشر: 2026-06-20 وقت القراءة: 9 دق

willSet و didSet هما مراقبا خاصية (property observers) في Swift يسمحان بتنفيذ كود قبل وبعد تغيير قيمة الخاصية. على عكس computed properties، لا تحسب المراقبات قيمة جديدة، بل تتفاعل فقط مع التغيير. وفقاً لوثائق Apple، The Swift Programming Language (2026)، لا غنى عن المراقبات للتحقق من صحة البيانات، ومزامنة الواجهة، وتسجيل التغييرات في الكود.

النقاط الرئيسية

  • willSet يُستدعى قبل حفظ القيمة الجديدة للخاصية
  • didSet يُستدعى بعد حفظ القيمة الجديدة
  • newValue معامل ضمني في willSet يحتوي على القيمة الجديدة
  • oldValue معامل ضمني في didSet يحتوي على القيمة القديمة
  • المراقبات لا تعمل أثناء التهيئة وداخل init

ما هما willSet و didSet في Swift؟

willSet و didSet هما مراقبا خاصية (property observers) في Swift، آلية مدمجة لتتبع التغييرات في stored properties.

على عكس اللغات الأخرى التي تتطلب تنفيذاً يدوياً للـ setters أو أنظمة الاستدعاء (callbacks)، يوفر Swift بناءً تصريحياً (declarative) للتفاعل مع التغييرات. تُضاف المراقبات مباشرة بعد تعريف الخاصية ولا تتطلب استدعاءً منفصلاً.

وفقاً لوثائق مطوري Apple (2026)، تدعم property observers الـ stored properties لأي class أو struct أو enum. لا تعمل مع computed properties لأنها لا تخزن قيمة — بالنسبة لها، يتم تنفيذ التفاعل مع التغيير مباشرة في الـ setter.

متى يُستدعى willSet

willSet يُستدعى مباشرة قبل تعيين قيمة جديدة للخاصية. داخل willSet، يتوفر المعامل الضمني newValue الذي يحتوي على القيمة التي سيتم تعيينها. في هذه اللحظة، لم تتغير قيمة الخاصية الحالية بعد — يمكنك قراءة القيمة القديمة مباشرة من خلال الخاصية.

وفقاً لاقتراح Swift Evolution SE-0001 (2024)، يوفر willSet إمكانية إجراء التحقق أو التسجيل قبل التغيير الفعلي. إذا تم طرح استثناء في willSet، لن يتم تطبيق القيمة الجديدة، مما يجعل المراقبات آلية لحماية البيانات.

متى يُستدعى didSet

didSet يُستدعى مباشرة بعد تعيين قيمة جديدة. داخل didSet، يتوفر المعامل الضمني oldValue الذي يحتوي على القيمة قبل التغيير. في هذه المرحلة، تحتوي الخاصية بالفعل على القيمة الجديدة، ويمكنك مقارنتها بالقيمة القديمة.

وفقاً لـ Swift by Sundell (2025)، didSet هو المراقب الأكثر شيوعاً لأنه يُستخدم غالباً للمعالجة اللاحقة: تحديث واجهة المستخدم، إعادة حساب الحقول التابعة، أو إرسال البيانات إلى الخادم بعد التغيير.

تركيب مراقبات الخاصية

تُعلن property observers مباشرة بعد الخاصية باستخدام الأقواس المتعرجة. يتطلب التركيب الأدنى مراقباً واحداً فقط، لكن يمكنك تعريف كليهما.

swift
var score: Int = 0 {
    willSet {
        print("ستتغير النتيجة إلى \(newValue)")
    }
    didSet {
        print("تغيرت النتيجة من \(oldValue) إلى \(score)")
    }
}

كلا المراقبين اختياريان — يمكنك تحديد willSet فقط أو didSet فقط. بالنسبة لـ willSet يمكنك إعادة تسمية newValue بتحديد اسم بين قوسين.

swift
var username: String = "guest" {
    willSet(newName) {
        print("على وشك تعيين \(newName)")
    }
    didSet(oldName) {
        print("كانت \(oldName)، الآن \(username)")
    }
}

وفقاً لـ Swift Language Guide (2026)، إعادة تسمية المعاملات تحسن قابلية قراءة الكود، خاصةً عند استخدام الخاصية والمراقبات في مشروع كبير بأسماء طويلة.

كيف يعمل willSet و didSet

ترتيب التنفيذ محدد بدقة: أولاً willSet (القيمة القديمة متاحة)، ثم التعيين، ثم didSet (القيمة الجديدة متاحة).

swift
class Temperature {
    var celsius: Double = 0.0 {
        willSet {
            print("ستتغير درجة الحرارة من \(celsius) إلى \(newValue)")
        }
        didSet {
            if celsius > 100.0 {
                print("تم تجاوز درجة الغليان!")
            }
        }
    }
}

قيد مهم: لا تُستدعى المراقبات أثناء تهيئة الخاصية عند إنشاء مثيل. داخل init، تعيين قيمة لا يُفعّل willSet و didSet — هذا يمنع الآثار الجانبية غير المرغوب فيها في مرحلة البناء.

وفقاً لمدونة Apple Swift Blog (2025)، يختلف هذا السلوك عن العديد من اللغات الأخرى حيث تُستدعى الـ setters حتى في المنشئات. Swift يختار الأمان: تبدأ المراقبات بالعمل فقط بعد اكتمال تهيئة الكائن.

الاستدعاءات المتداخلة والتكرار

تغيير خاصية داخل didSet قد يؤدي إلى استدعاءات متكررة للمراقب. Swift لا يمنع التكرار — يجب على المبرمج التحكم فيه يدوياً.

swift
var counter: Int = 0 {
    didSet {
        if counter < 5 {
            counter += 1
        }
    }
}

هذا الكود سيخلق تكراراً كاملاً مع تجاوز سعة المكدس إذا لم يتم توفير شرط خروج. وفقاً لمجتمع Stack Overflow Swift (2025)، هذا أحد أكثر الأخطاء شيوعاً التي يرتكبها المبتدئون عند العمل مع property observers.

مراقبات خصائص الـ structs

الـ structs تدعم willSet و didSet لـ stored properties بدون قيود. من المهم تذكر أن الـ structs هي أنواع قيمة (value types)، وتعديل خاصية داخل دالة mutating يُفعّل أيضاً المراقبات.

swift
struct Point {
    var x: Double = 0.0 {
        didSet {
            print("تغير X إلى \(x)")
        }
    }
    var y: Double = 0.0 {
        didSet {
            print("تغير Y إلى \(y)")
        }
    }
}

var point = Point()
point.x = 5.0

استخدام المراقبات في المشاريع الحقيقية

تُستخدم مراقبات الخاصية في مشاريع Swift لمجموعة واسعة من المهام: من مزامنة واجهة المستخدم إلى التحقق من البيانات والتسجيل.

التحقق من القيم

didSet يسمح بتراجع أو تصحيح قيمة غير صالحة فور تعيينها. هذا يستبدل الـ setters المرهقة في Objective-C ويضمن سلامة البيانات على مستوى النموذج.

swift
var age: Int = 0 {
    didSet {
        if age < 0 || age > 150 {
            age = oldValue
        }
    }
}

مزامنة واجهة المستخدم

عند تغيير خاصية مرتبطة، يمكنك تحديث عناصر الواجهة تلقائياً بدون استدعاء منفصل لدالة التحديث.

swift
var userName: String = "" {
    didSet {
        nameLabel.text = userName
    }
}

تسجيل التغييرات

willSet مناسب للتسجيل بغرض التصحيح أو المراجعة. يمكنك تسجيل الوقت والقيمة الجديدة قبل تطبيقها، مما يضمن أن السجل يحتوي على البيانات الأصلية للتحليل.

وفقاً لـ objc.io (2025)، تعتبر property observers مفيدة بشكل خاص في البنى ذات تدفق البيانات أحادي الاتجاه، حيث يتم تسجيل كل تغيير في الخاصية لإعادة إنتاج الحالة لاحقاً.

المقارنة مع computed properties

الـ computed properties تحسب القيمة فورياً وليس لها مخزن، بينما يعمل willSet و didSet على stored property بقيمة فعلية.

الخاصيةProperty ObserversComputed Properties
تخزين القيمةنعملا
تنفيذ كود عند التغييرنعملا
نوع التعريفvarvar (get/set)
معاملات الوصولnewValue, oldValuenewValue (في set)
التهيئةتتطلب قيمة أوليةغير مطلوبة

الفرق الرئيسي: computed property تحسب القيمة عند كل وصول، بينما يتفاعل property observer مع تغيير قيمة موجودة. الاختيار بينهما تمليه الدلالات — إذا كانت الخاصية مشتقة من بيانات أخرى، استخدم computed؛ إذا كانت قيمة مستقلة يجب مراقبة تغييراتها، استخدم willSet/didSet.

الأخطاء الشائعة عند الاستخدام

الخطأ الأكثر شيوعاً هو الاستدعاء التكراري لـ didSet بدون شرط خروج. كل تغيير في الخاصية داخل didSet يُفعّل المراقب مرة أخرى، مما يؤدي إلى حلقة لا نهائية.

الخطأ الثاني الشائع هو محاولة استخدام المراقبات على خصائص let. سيصدر مترجم Swift خطأ لأن let ثابت.

الخطأ الثالث هو تجاهل أن المراقب لا يُستدعى أثناء التهيئة. المطورون الذين يتوقعون تفعيل willSet داخل init يحصلون على سلوك غير متوقع.

المشكلة الرابعة هي تطبيق المراقبات على الخصائص في extension. يمنع Swift إضافة willSet/didSet إلى stored properties في extension.

وفقاً لـ Ray Wenderlich (2025)، فهم هذه القيود يساعد في تجنب الأخطاء في المراحل المبكرة ويجعل كود Swift أكثر قابلية للتنبؤ.

الأسئلة الشائعة

هل يمكن استخدام willSet بدون didSet؟

نعم، كل مراقب اختياري. يمكنك تعريف willSet فقط، أو didSet فقط، أو كليهما معاً.

هل تعمل المراقبات في extension؟

لا، Swift يمنع إضافة willSet و didSet في extension للـ stored properties. تُعلن المراقبات فقط في تعريف النوع الأصلي.

هل تُستدعى المراقبات عند تغيير خاصية داخل init؟

لا، المراقبات لا تُستدعى أثناء التهيئة. هذه آلية حماية تمنع الآثار الجانبية في مرحلة بناء الكائن.

كيف يختلف willSet عن setter في computed property؟

willSet هو مراقب stored property يُنفذ قبل تغيير القيمة. الـ setter في computed property هو طريقة لحساب قيمة جديدة، وليس مراقبة لقيمة موجودة.

ماذا يحدث عند تغيير خاصية داخل didSet؟

استدعاء متكرر لـ didSet سيسبب تكراراً. بدون شرط خروج، يؤدي ذلك إلى تجاوز سعة المكدس وإنهاء البرنامج.

الخلاصة

  • willSet مراقب يُنفذ قبل تغيير الخاصية، مع إمكانية الوصول إلى newValue
  • didSet مراقب يُنفذ بعد تغيير الخاصية، مع إمكانية الوصول إلى oldValue
  • التركيب — تُعلن المراقبات بين الأقواس المتعرجة بعد تعريف الخاصية
  • التهيئة — لا تعمل المراقبات داخل init وعند تعيين قيمة افتراضية
  • الاستخدام — التحقق، مزامنة واجهة المستخدم، التسجيل، مراجعة التغييرات
  • التكرار — تغيير خاصية داخل didSet يتطلب شرط خروج صريح
  • Computed — لا تخلط مع computed properties: المراقبات تراقب، computed تحسب

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا