- كل المقالات
- مراقبات الخصائص تعطيك القيمة القديمة والجديدة أصلًا
مراقبات الخصائص تعطيك القيمة القديمة والجديدة أصلًا
يأخذ كلٌّ من willSet وdidSet وسيطًا، ولكلٍّ منهما اسم افتراضي، فتسميته صراحةً زيادةٌ في الغالب. أما القواعد المتعلقة بمتى لا تعمل فأهمّ.
يستقبل كلٌّ من willSet وdidSet القيمة الناقصة عنده: يأخذ willSet القيمة
الداخلة، ويأخذ didSet القيمة السابقة. ولكلٍّ منهما اسم افتراضي، فهذا يُترجَم
كما هو مكتوب:
var language = "ObjC" {
willSet {
print("about to replace \(language) with \(newValue)")
}
didSet {
print("replaced \(oldValue) with \(language)")
}
}
ويقرأ كل مراقب قيمةً من الوسيط والأخرى من الخاصية: ففي willSet تكون الخاصية
ما زالت تحمل القيمة القديمة، وفي didSet تكون قد صارت تحمل الجديدة.
أما الصيغة الصريحة — willSet(newValue) وdidSet(oldValue) — فتسمّي الوسيط
باسمه الافتراضي نفسه، فلا تضيف شيئًا. وإنما تُكتب حين يكون اسم آخر أوضح:
didSet(previousUser) {
guard previousUser.id != user.id else { return }
reload()
}
ومتى لا تعمل هذه المراقبات أكثر إثارةً للالتباس من أسماء وسائطها. وفي ذلك ثلاث قواعد.
لا تعمل أثناء التهيئة
الإسناد إلى خاصية من داخل init لا يستدعي مراقباتها، بما في ذلك عبر
الـmemberwise initializer. وما كان من الإعداد موضعه didSet فلا بدّ من
استدعائه صراحةً في آخر init، وإلا لم يقع مع أول قيمة دون أن يظهر لذلك أثر.
لا تعمل عند الإسناد من داخل didSet
الكتابة إلى الخاصية داخل didSet الخاص بها لا تدخل المراقب من جديد، وهذا ما
يمنع التكرار اللانهائي. فـdidSet الذي يحدّ قيمته أو يضبطها بنفسه يعمل، والذي
كُتب على انتظار أن ترجع إليه كتابته لا يعمل.
تعمل مع كل كتابة، لا مع كل تغيير
إسناد القيمة نفسها إلى الخاصية يشغّل المراقبين. وإن كان المتن يستدعي إعادة تحميل أو إعادة تخطيط، ففحص التساوي هو المقصود عادةً:
didSet {
guard oldValue != items else { return }
tableView.reloadData()
}
والأمر نفسه يسري على المستوى الذي تحته: فإن كانت الخاصية تحمل struct، فتعديل
أحد حقولها كتابةٌ إلى الخاصية كلّها، فـsettings.fontSize = 14 تشغّل didSet
على settings — وهذا ممّا ينبغي معرفته قبل وضع عمل ثقيل في أحدها.