تفاعلات Swift: متابعات الخصائص وتحديات الدوال المتغيرة
في عالم برمجة Swift، لغة البرمجة التي طورتها شركة آبل، يظهر أن مستخدمي اللغة يواجهون أحيانًا تفاعلات غريبة أو غير متوقعة بين الخصائص والدوال التي تتعامل مع تحديثات القيم. من بين هذه الحالات الغريبة تأتي تأثير الـ didSet
في Swift على دوال mutating
، وهو ما سنتناوله في هذا النص.
لقد اكتسبت المعرفة الجديدة حول كيفية عمل الدوال المتغيرة (mutating functions
) في Swift، حيث أصبح من الواضح أنها في الأساس تعتبر دوالًا مطوية (curried functions
) مع المعامل الأول من نوع inout
. هذا الفهم يتيح للمبرمجين استخدام دوال mutating
بطريقة أكثر مرونة وفهماً.
-
تقييد أنواع الأخطاء في Swift31/03/2024
-
عرض بيانات JSON في UICollectionView07/03/2024
لديك الكود التالي:
swiftstruct Person {
var firstName = "Matt"
mutating func changeName(fn: String) {
firstName = fn
}
}
var p = Person()
let changer = Person.changeName
changer(&p)("John")
print(p.firstName)
هذا الكود يظهر كيف يمكن استخدام دالة mutating
باستخدام الكيرينغ. ولكن، عند إضافة متابع الخصائص (property observer
) إلى الكود:
swiftvar p = Person() {
didSet {
print("Property observer called")
}
}
let changer = Person.changeName
changer(&p)("John")
print(p.firstName)
ستجد أن قيمة firstName
لم تتغير، وهو الأمر الذي قد يظهر متناقضًا بعض الشيء. السبب وراء هذا يعود إلى الشكل الذي يتم توليد الـ setter
به.
بشكل عام، عندما يتم تغيير قيمة خاصية (property
) في Swift، يتم تنفيذ متابع الخصائص (property observer) أولاً، ثم يتم تنفيذ الـ didSet
. وبما أن الدالة changeName
هي mutating
وتؤثر على الخصائص، يحدث التالي:
- يتم استدعاء متابع الخصائص (
property observer
) وتقديم قيمة جديدة للخاصيةp
، ولكن لا توجد عمليات تغيير داخله. - يتم استدعاء الـ
didSet
وهنا يحدث تغيير في قيمة الخاصيةp
باستخدام دالةchangeName
.
وهنا يكمن السر، فالتغيير الذي يتم في الخاصية داخل دالة changeName
لا ينعكس على القيمة المستخدمة في متابع الخصائص، حيث يتم استخدام قيمة مؤقتة داخل الـ setter
للتحكم في عملية تنفيذه.
من هنا، يمكن أن يكون الحل هو تغيير بنية الكود لضمان تحديث الخاصية بشكل صحيح. يمكن تجربة ذلك عبر تغيير الكود كما يلي:
swiftvar p = Person() {
didSet {
p.changeName(fn: p.firstName)
}
}
let changer = Person.changeName
changer(&p)("John")
print(p.firstName)
بهذا الشكل، يتم استخدام قيمة جديدة للـ firstName
في متابع الخاصية وتمريرها إلى الدالة changeName
بطريقة تضمن التحديث الصحيح للخاصية.
المزيد من المعلومات
لفهم أفضل للتفاعلات الغريبة التي قد تحدث بين متابعات الخصائص (property observers
) والدوال المتغيرة (mutating functions
) في Swift، يمكننا التركيز على بعض النقاط الإضافية والتفاصيل التقنية.
-
ترتيب تنفيذ الأحداث:
يتم تنفيذ متابعات الخصائص قبل تنفيذ الكود الموجود داخل دوالdidSet
. هذا يعني أن أي تغيير في قيمة الخاصية يحدث أولاً في سياق متابعة الخاصية، ومن ثم يتم استدعاءdidSet
. -
تأخير تنفيذ الـ
didSet
:
عند إضافة متابع للخاصيةdidSet
، يتم تأخير تنفيذ الكود داخلها حتى يتم استكمال تنفيذ السياق الحالي، وهذا يشمل تنفيذ متابعات الخصائص. -
نمط البرمجة الوظيفي والتأثير الجانبي:
في Swift، يشجع على استخدام أسلوب البرمجة الوظيفي وتجنب التأثيرات الجانبية. دوالmutating
تقوم بتعديل الحالة الداخلية للهيكل (struct
) أو الفئة (class
)، ويجب فهم الآثار المحتملة لذلك عند استخدامها مع متابعات الخصائص. -
استخدام
willSet
:
بالإضافة إلىdidSet
، يمكن أيضًا استخدامwillSet
كمتابع للخصائص، والذي يُستدعى قبل أن يتم تعيين القيمة الجديدة. هذا يوفر فرصة لتغيير القيمة المراد تعيينها. -
تأثير التجميع (Closures Capturing):
قد يكون لديك تأثير للتجميع في Swift عند استخدام المتغيرات في دوال أو متابعات. يجب عليك فهم كيف يتم التعامل مع التجميع وكيف يمكن أن يؤثر ذلك على تنفيذ الشيفرة.
من المهم أن تكون حذرًا وواعيًا للآثار الجانبية المحتملة عند استخدام دوال mutating
في Swift، خاصةً عندما تكون هناك تفاعلات مع متابعات الخصائص. يوفر الفهم العميق لهذه التفاعلات أداة أساسية لتطوير تطبيقات قوية وسليمة في Swift.