willSet و didSet هما مراقبا خاصية (property observers) في Swift يسمحان بتنفيذ كود قبل وبعد تغيير قيمة الخاصية. على عكس computed properties، لا تحسب المراقبات قيمة جديدة، بل تتفاعل فقط مع التغيير. وفقاً لوثائق Apple، The Swift Programming Language (2026)، لا غنى عن المراقبات للتحقق من صحة البيانات، ومزامنة الواجهة، وتسجيل التغييرات في الكود.
النقاط الرئيسية
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، يتوفر المعامل الضمني newValue الذي يحتوي على القيمة التي سيتم تعيينها. في هذه اللحظة، لم تتغير قيمة الخاصية الحالية بعد — يمكنك قراءة القيمة القديمة مباشرة من خلال الخاصية.
وفقاً لاقتراح Swift Evolution SE-0001 (2024)، يوفر willSet إمكانية إجراء التحقق أو التسجيل قبل التغيير الفعلي. إذا تم طرح استثناء في willSet، لن يتم تطبيق القيمة الجديدة، مما يجعل المراقبات آلية لحماية البيانات.
didSet يُستدعى مباشرة بعد تعيين قيمة جديدة. داخل didSet، يتوفر المعامل الضمني oldValue الذي يحتوي على القيمة قبل التغيير. في هذه المرحلة، تحتوي الخاصية بالفعل على القيمة الجديدة، ويمكنك مقارنتها بالقيمة القديمة.
وفقاً لـ Swift by Sundell (2025)، didSet هو المراقب الأكثر شيوعاً لأنه يُستخدم غالباً للمعالجة اللاحقة: تحديث واجهة المستخدم، إعادة حساب الحقول التابعة، أو إرسال البيانات إلى الخادم بعد التغيير.
تُعلن property observers مباشرة بعد الخاصية باستخدام الأقواس المتعرجة. يتطلب التركيب الأدنى مراقباً واحداً فقط، لكن يمكنك تعريف كليهما.
var score: Int = 0 {
willSet {
print("ستتغير النتيجة إلى \(newValue)")
}
didSet {
print("تغيرت النتيجة من \(oldValue) إلى \(score)")
}
}
كلا المراقبين اختياريان — يمكنك تحديد willSet فقط أو didSet فقط. بالنسبة لـ willSet يمكنك إعادة تسمية newValue بتحديد اسم بين قوسين.
var username: String = "guest" {
willSet(newName) {
print("على وشك تعيين \(newName)")
}
didSet(oldName) {
print("كانت \(oldName)، الآن \(username)")
}
}
وفقاً لـ Swift Language Guide (2026)، إعادة تسمية المعاملات تحسن قابلية قراءة الكود، خاصةً عند استخدام الخاصية والمراقبات في مشروع كبير بأسماء طويلة.
ترتيب التنفيذ محدد بدقة: أولاً willSet (القيمة القديمة متاحة)، ثم التعيين، ثم didSet (القيمة الجديدة متاحة).
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 لا يمنع التكرار — يجب على المبرمج التحكم فيه يدوياً.
var counter: Int = 0 {
didSet {
if counter < 5 {
counter += 1
}
}
}
هذا الكود سيخلق تكراراً كاملاً مع تجاوز سعة المكدس إذا لم يتم توفير شرط خروج. وفقاً لمجتمع Stack Overflow Swift (2025)، هذا أحد أكثر الأخطاء شيوعاً التي يرتكبها المبتدئون عند العمل مع property observers.
الـ structs تدعم willSet و didSet لـ stored properties بدون قيود. من المهم تذكر أن الـ structs هي أنواع قيمة (value types)، وتعديل خاصية داخل دالة mutating يُفعّل أيضاً المراقبات.
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 ويضمن سلامة البيانات على مستوى النموذج.
var age: Int = 0 {
didSet {
if age < 0 || age > 150 {
age = oldValue
}
}
}
عند تغيير خاصية مرتبطة، يمكنك تحديث عناصر الواجهة تلقائياً بدون استدعاء منفصل لدالة التحديث.
var userName: String = "" {
didSet {
nameLabel.text = userName
}
}
willSet مناسب للتسجيل بغرض التصحيح أو المراجعة. يمكنك تسجيل الوقت والقيمة الجديدة قبل تطبيقها، مما يضمن أن السجل يحتوي على البيانات الأصلية للتحليل.
وفقاً لـ objc.io (2025)، تعتبر property observers مفيدة بشكل خاص في البنى ذات تدفق البيانات أحادي الاتجاه، حيث يتم تسجيل كل تغيير في الخاصية لإعادة إنتاج الحالة لاحقاً.
الـ computed properties تحسب القيمة فورياً وليس لها مخزن، بينما يعمل willSet و didSet على stored property بقيمة فعلية.
| الخاصية | Property Observers | Computed Properties |
|---|---|---|
| تخزين القيمة | نعم | لا |
| تنفيذ كود عند التغيير | نعم | لا |
| نوع التعريف | var | var (get/set) |
| معاملات الوصول | newValue, oldValue | newValue (في 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 فقط، أو كليهما معاً.
لا، Swift يمنع إضافة willSet و didSet في extension للـ stored properties. تُعلن المراقبات فقط في تعريف النوع الأصلي.
لا، المراقبات لا تُستدعى أثناء التهيئة. هذه آلية حماية تمنع الآثار الجانبية في مرحلة بناء الكائن.
willSet هو مراقب stored property يُنفذ قبل تغيير القيمة. الـ setter في computed property هو طريقة لحساب قيمة جديدة، وليس مراقبة لقيمة موجودة.
استدعاء متكرر لـ didSet سيسبب تكراراً. بدون شرط خروج، يؤدي ذلك إلى تجاوز سعة المكدس وإنهاء البرنامج.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا