Back home

SwiftUI Series 04|إدارة حالة SwiftUI: اختيارState وBinding وObservedObject وStateObject

المفتاح الحقيقي هو الإجابة أولاً على "من يملك هذه البيانات ومن يقود تغييرات الواجهة؟"

المكان الذي من المرجح أن يعلق فيه الأشخاص في SwiftUI هو الولاية.

الأسئلة الأكثر شيوعا هي عادة ما يلي:

  • هل يجب أن نستخدم @State أو @Binding لهذه القيمة؟
  • ستتم تهيئة ViewModel بشكل متكرر
  • لماذا لا يستطيع العرض الفرعي تغيير بيانات العرض الأصلي؟
  • لقد تغيرت القيمة بشكل واضح، ولكن لم يتم تحديث الصفحة كما هو متوقع.

إذا كنت تعتمد فقط على حفظ أغلفة السمات لحل هذه المشكلات، فمن السهل أن تصبح مرتبكًا أكثر فأكثر. لأن السبب الجذري الحقيقي هو عادة:

دون أن نفكر أولاً بوضوح في “من يملك هذه الدولة؟”

1. لا تتعجل في اختيار الغلاف. اسأل أولاً: لمن هذه البيانات؟

هذا هو السؤال الأهم.

في SwiftUI، في كل مرة ترى فيها قيمة حالة، اسأل نفسك:

  • هل هذه القيمة مملوكة للعرض الحالي؟
  • لا يزال العرض الأصلي مملوكًا له، ويتم استعارة العرض الفرعي وتعديله فقط.
  • لا يزال مملوكًا لكائن خارجي، أما العرض الحالي فهو مجرد ملاحظة

بمجرد الإجابة على هذا السؤال بوضوح، ستظهر العديد من خيارات الأغلفة بشكل طبيعي. على العكس من ذلك، إذا تخطيت هذه الخطوة وتساءلت مباشرة “أيها شائع الاستخدام في هذا السيناريو”، فسيكون من السهل تجميع التعليمات البرمجية عن طريق التجربة والخطأ.

2. @State مناسب حقًا لـ “الحالة المحلية للعرض الحالي”

@State هو الأكثر ملاءمة لـ:

هذه الحالة تنتمي فقط إلى العرض الحالي. إن الوجود المحلي والاستهلاك المحلي وترك هذا العرض لا معنى له في الأساس.

على سبيل المثال:

  • المحتوى الحالي لمربع الإدخال
  • سواء لعرض الورقة
  • حالة معينة من التوسع والانهيار جزئيا
  • اختيار علامة التبويب الحالية

ما تشترك فيه هذه الدول هو:

  • ملكية واضحة
  • إن دورة الحياة مرتبطة بقوة بهذا الرأي
  • لا يستحق الترقية إلى حالة العمل الخارجي

إذا لم يكن هناك معنى لجزء من الحالة خارج العرض الحالي، فعادةً ما يكون مناسبًا لـ @State.

3. النقطة الأساسية في @Binding هي أن “الملكية لم تتغير، ولكن تم إعارة إذن الكتابة”

الموقف الشائع هو فهم @Binding على أنه “يمكن لطرق العرض الفرعية أيضًا تغيير قيمة العرض الأصلي”. وهذا الفهم ليس خاطئا، لكنه ليس دقيقا بما فيه الكفاية.

ما هو أكثر من ذلك:

  • هذه الحالة لا تزال تنتمي إلى العرض الأصلي
  • العرض الفرعي لا يملكه
  • يحصل العرض الفرعي على قنوات القراءة والكتابة فقط

يعد هذا الأمر بالغ الأهمية لأنه يحدد ما إذا كان سيتم الاحتفاظ بإسناد البيانات الصحيح عند تسجيل المكون.

وهذا يعني:

  • @State هو “خاص بي”
  • @Binding “لا يزال كما هو، ولكنني مخول بتغييره”

بمجرد فهم @Binding من حيث الملكية، لم يعد من الممكن الخلط بينه وبين “حل واحد لمشاركة البيانات يناسب الجميع”.

4. من السهل الخلط بين @ObservedObject و@StateObject لأن الناس غالبًا ما يخلطون بين “الملاحظة” و"الحيازة".

سوء الاستخدام الأكثر شيوعًا لهذين الغلافين يأتي أساسًا من نفس المشكلة:

ليس من الواضح ما إذا كان “العرض الحالي يراقب كائنًا خارجيًا” أو “العرض الحالي ينشئ هذا الكائن ويحتفظ به بشكل ثابت”.

@ObservedObject

من الأفضل التعبير عن:

  • يتم تمرير هذا الكائن من الخارج
  • العرض الحالي يلاحظه فقط
  • العرض الحالي ليس مسؤولاً عن إنشائه، ولا هو مسؤول عن ثباته

@StateObject

من الأفضل التعبير عن:

  • يقوم العرض الحالي بإنشاء هذا الكائن بنفسه
  • وتريد الاحتفاظ به بثبات أثناء تحديث العرض

والفرق الأساسي بين الاثنين ليس “أيهما أكثر تقدما”، بل:

  • من خلق الكائن
  • من المسؤول عن دورة حياة الكائن

يوضح هذا أيضًا أن العديد من مشكلات التهيئة المتكررة لـ ViewModel هي في الأساس ملكية كائن في غير محلها.

5. حكم هندسي عملي للغاية: يجب التفكير في حالة واجهة المستخدم المحلية وحالة العمل بشكل منفصل

ستكون حالة العديد من الصفحات مربكة، وسيتم تجميع حالة المستويات المختلفة في كرة.

على سبيل المثال، قد تحتوي الصفحة على:

  • محتوى صندوق الإدخال
  • قم بتصفية ما إذا كانت النافذة المنبثقة مفتوحة أم لا
  • نتائج طلب الشبكة
  • حالة تحميل الصفحة
  • قائمة كائنات الأعمال

يبدو أن هذه القيم تسمى “حالة”، ولكنها ليست نفس نوع الحالة.

عادةً ما أقسمها تقريبًا إلى فئتين:

1. حالة واجهة المستخدم المحلية

على سبيل المثال:

  • سواء للتوسع
  • محتوى الإدخال الحالي
  • العنصر المحدد حاليا
  • تبديل العرض الجزئي

هذا النوع من الحالة أقرب إلى @State / @Binding.

2. حالة بيانات العمل

على سبيل المثال:

  • معلومات المستخدم
  • قائمة البيانات
  • عملية التحميل
  • خطأ في الطلب

عادةً ما يتم وضع هذا النوع من الحالات بشكل أفضل في كائن خارجي يمكن ملاحظته أو حاوية حالة ذات مستوى أعلى.

بمجرد عدم التمييز بين هذين النوعين من الحالات، سيكون للصفحة بسهولة الحالة المحلية وحالة ViewModel وقيم تمرير الطبقة الأصلية. وفي النهاية، ليس من الواضح من يملكها.

6. العديد من مشكلات “القيمة تغيرت ولكن الواجهة خاطئة” ترجع أساسًا إلى اختلاط حدود الحالة.

الوضع الشائع هو أن:

  • من الواضح أنني غيرت القيمة، لكن لماذا لم تتغير الصفحة كما كنت أعتقد؟

هذا بالطبع هو الغلاف الخاطئ في بعض الأحيان، ولكن في كثير من الأحيان:

  • الحالة التي يجب أن تكون مملوكة للطبقة الأم، تحتفظ بها الطبقة الفرعية مؤقتًا.
  • يتم التعامل مع الكائنات التي كان من المفترض أن تكون موجودة لفترة طويلة على أنها كائنات مراقبة مؤقتة.
  • استبدال حالة واجهة المستخدم المحلية وحالة العمل ببعضهما البعض

بمعنى آخر، ما يبدو وكأنه “مشكلة تحديث” غالبًا ما يكون في الواقع مشكلة ملكية.

بالنسبة للعديد من مشكلات الحالة في SwiftUI، بمجرد تحديد “من يملك هذه البيانات”، يمكنك عادةً العثور على السبب الجذري بشكل أسرع من التحديق في ظاهرة الواجهة.

7. طريقة حكم مبسطة أستخدمها كثيرًا

على الرغم من أن المشاريع الحقيقية ستكون أكثر تعقيدًا، إلا أنني غالبًا ما أستخدم هذه المجموعة من الأحكام البسيطة في التطوير اليومي:

1. هل هذه هي الحالة البسيطة للعرض الحالي نفسه؟

نعم، أعط الأولوية لـ @State

2. هل هذا مملوك للعرض الأصلي وتم استعارته وتعديله بواسطة العرض الفرعي الحالي؟

نعم، أعط الأولوية لـ @Binding

3. هل هذا جسم يمكن ملاحظته وتم تمريره من الخارج؟

نعم، أعط الأولوية لـ @ObservedObject

4. هل هذا هو الكائن الذي أنشأه العرض الحالي ويأمل أن يظل ثابتًا؟

نعم، أعط الأولوية لـ @StateObject

من المؤكد أن هذه المجموعة من الأحكام لا تغطي كافة التفاصيل، ولكنها عملية بما يكفي لعدد كبير من صفحات الأعمال.

8. الخلاصة: ما نحتاج حقاً إلى فهمه أولاً حول إدارة الدولة هو الملكية.

ولكي أختصر الأمر أقول:

في SwiftUI، أهم شيء في إدارة الحالة هو أن نسأل أولاً “من يملك هذه البيانات ومن المسؤول عن تغيير الواجهة معها.”

بمجرد أن تصبح الملكية واضحة أولاً، فإن العديد من خيارات الأغلفة ستأتي بشكل طبيعي. من ناحية أخرى، إذا لم تفكر بوضوح في الملكية وتعرفت على واجهة برمجة التطبيقات (API) لاحقًا، فسيكون من السهل كتابة صفحة “تعمل ولكنها تصبح فوضوية بشكل متزايد”.

FAQ

What to read next

Related

Continue reading