SwiftUI Series 10|SwiftUI التحميل غير المتزامن: المهام، والمزامنة/الانتظار، وربط حالة الواجهة
الأمر الصعب حقًا هو الحفاظ على اتساق التحميل والنتائج والأخطاء ودورة حياة الصفحة
بمجرد تحميل العديد من صفحات SwiftUI بشكل غير متزامن، تبدأ المشكلات في التزايد:
- سوف يقوم
onAppearبتكرار الطلب - حالة التحميل غير مستقرة
- النتائج القديمة سوف تغير الصفحة الحالية مرة أخرى
- لا تزال تتم إعادة كتابة المهمة بعد مغادرة الصفحة
قد تبدو هذه المشاكل مثل مشاكل Task أو async/await على السطح، ولكن الأسباب الأكثر جوهرية غالبًا ما تكون:
لا تتم محاذاة دورة حياة المهمة غير المتزامنة ودورة حياة حالة الصفحة.
لذا فإن ما يتعين علينا التعامل معه حقًا هو:
- متى يبدأ الطلب؟
- هل سأكون مؤهلاً لتغيير الصفحة بعد ظهور النتائج؟
- متى يجب أن تنتهي المهام القديمة؟
- كيف يتم تحميل/خطأ/محتوى هذه الحالات بشكل حصري؟
1. المأزق الأسهل هو اعتبار الصفحة غير متزامنة على أنها “طلب واحد + قيمة منطقية واحدة”
سيتم كتابة العديد من الصفحات في البداية على النحو التالي:
isLoadingitemserrorMessage
أضف واحدًا آخر:
Task {
await load()
}
بالطبع سيعمل في البداية، ولكن بمجرد أن تبدأ الصفحة في دعم:
- حاول مرة أخرى
- اسحب للأسفل للتحديث
- بحث
- التبديل المشروط
سوف تنشأ المشاكل واحدة تلو الأخرى. لأن الصفحة الحقيقية هي مجموعة من المهام التي قد تحل محل بعضها البعض ويغطي بعضها البعض.
2. يكمن الجوهر الحقيقي للصفحات غير المتزامنة في تدفق الحالة
إذا كنت تفهم التحميل غير المتزامن فقط على أنه “استعادة البيانات”، فسيكون من السهل تجاهل أن ما تهتم به الصفحة حقًا هو الحالات التالية:
- التحميل عند الدخول لأول مرة
- التحديث بناءً على المحتوى الموجود
- أعد المحاولة بعد فشل التحميل
- الطلب بعد تغير شروط معينة
كلاهما “تحميلات”، لكنهما ليسا نفس الشيء في دلالات الصفحة.
إذا تم تمثيل كل شيء بواسطة isLoading واحد فقط، فستصبح الصفحة فوضوية قريبًا.
لذا فإن الفكرة الأكثر عملية عادة ما تكون:
- حدد أولاً الحالة الدلالية التي توجد بها الصفحة حاليًا
- دع المهمة غير المتزامنة تقود إلى تغيير تدفق الحالة هذا
3. غالبًا ما يصبح onAppear + Task أكثر خطورة كلما كتبته أكثر.
لأنه من السهل جدا.
الموقف الشائع هو أن تكتب بشكل طبيعي:
.onAppear {
Task {
await viewModel.load()
}
}
هذا الرمز في حد ذاته ليس بالضرورة خاطئًا، ولكن الخطر يكمن في أنه من السهل جدًا تعيينه افتراضيًا على النحو التالي:
- تظهر الصفحة مرة واحدة
- طلب الإرسال مرة واحدة
- تغيير الحالة مرة واحدة بعد العودة
في المشاريع الحقيقية، قد لا تكون هذه الافتراضات الثلاثة صحيحة.
لذلك، فإن المفتاح لمعرفة ما إذا كان التحميل غير المتزامن مستقرًا حقًا ليس ما إذا كان هناك Task، بل بالأحرى:
- ما إذا كانت المهام المماثلة تدار بشكل موحد -هل سيتم إلغاء المهام القديمة أو انتهاء صلاحيتها
- ما إذا كانت النتيجة بحاجة إلى التحقق منها في ضوء السياق الحالي
4. سوء فهم شائع: إذا كانت النتيجة ناجحة، فسوف تصل مباشرة إلى الصفحة.
العديد من الصفحات في حالة مضطربة، والسبب الجذري هنا.
على سبيل المثال:
- لقد تغيرت الكلمات الرئيسية
- الطلبات القديمة تعود لاحقا
- النتائج القديمة لا تزال تغير الصفحة
من منظور الطلب لم يفشل، ولكن من منظور الصفحة انتهت صلاحيته.
لذا فإن أحد الأشياء المهمة جدًا في الصفحات غير المتزامنة هو:
ليست كل النتائج التي تم إرجاعها بنجاح مؤهلة تلقائيًا لإعادة كتابة واجهة المستخدم الحالية.
لذلك، عادة لا يمكن للتحميل غير المتزامن للصفحات أن ينظر فقط إلى “ما إذا كانت النتيجة قد تم الحصول عليها”، ولكن يجب أيضًا أن ينظر إلى “ما إذا كانت النتيجة لا تزال صالحة الآن”.
5. اتجاه أكثر استقرارًا: أغلق مهمة التحميل بدلاً من السماح لكل حدث واجهة مستخدم بإرسال طلبه الخاص
إذا كانت الصفحة تدعم:
- التحميل الأولي
- حاول مرة أخرى
- تحديث
- تصفية التغييرات
عادة ما يكون النهج الأكثر استقرارًا هو تجميع المهام المتشابهة معًا.
على سبيل المثال:
- جميع الإدخالات تستدعي في النهاية نفس
reload() - يتم الاحتفاظ بالمهمة النشطة حاليًا بواسطة ViewModel
- عند ظهور مهام جديدة، يتم إلغاء المهام القديمة أو الحكم بأنها غير صالحة.
بهذه الطريقة ستكون حالة الصفحة على الأقل أسهل في الحفاظ على اتساقها للأسباب التالية:
- من الواضح من يقوم بالتحميل
- ومن الواضح أيضًا من يمكنه إنهاء التحميل
6. الاستنتاج: ما يحتاج التحميل غير المتزامن لـ SwiftUI للتعامل معه هو ما إذا كان من الممكن شرح حالة المهمة والصفحة بوضوح.
ولكي أختصر الأمر أقول:
عند التعامل مع التحميل غير المتزامن في SwiftUI، تكمن الصعوبة الحقيقية في الحفاظ على اتساق دورة حياة المهمة وصلاحية النتيجة وتدفق حالة الصفحة.
وطالما لم يتم إنشاء هذه الأشياء الثلاثة، ستستمر الصفحة في النمو:
- كرر الطلب
- إعادة كتابة النتائج القديمة
- ارتباك التحميل
لا يمكن عادة إصلاح هذه المشكلات عن طريق كتابة المزيد من Task.
What to read next
Want more posts about SwiftUI?
Posts in the same category are usually the best next step for reading more on this topic.
View same categoryWant to keep following #iOS?
Tags are useful for related tools, specific problems, and similar troubleshooting notes.
View same tagWant to explore another direction?
If you are not sure what to read next, return to the homepage and start from categories, topics, or latest updates.
Back home