iOS / Swift / التزامن وحدود البيانات / الدرس 7
async وawait والإلغاء المنظم
افهم التعليق والإلغاء التعاوني قبل ربط المهام بعمر الشاشة.
في هذه الصفحة
أهداف الدرس
- تصف async التعليق لا خيطا خلفيا
- تنتمي المهام الأبناء المنظمة إلى نطاقها
- انتظر نتائج مصطنعة مستقلة
تصف async التعليق لا خيطا خلفيا
يمكن للدالة async التعليق عند await ثم المتابعة لاحقا. ولا تَعِد بأن يجري كل عملها على خيط خلفي أو أن تصبح حلقة حسابية ثقيلة مستجيبة تلقائيا. يعتمد سلوك المنفذ على تعليقات العزل ونمط Swift المختار وإعدادات المشروع التي قد تتطور بين الأدوات. اذكر الافتراضات عند شرح الأداء أو التشخيص. اجعل الحالة المتغيرة المتصلة بالواجهة معزولة صراحة على الممثل الرئيسي في أمثلة الدورة. وعامل كل await كحد قد يعمل خلاله غيرك وتتقادم المدخلات أو الملكية.
تنتمي المهام الأبناء المنظمة إلى نطاقها
يبدأ ارتباط async let مهمة ابنة يحد نطاقها المحيط عمرها. وتنظم مجموعة المهام عملا مرتبطا وتوضح سياسة الاكتمال والخطأ. استخدم التزامن حين تستقل العمليات، لا حين تحتاج الثانية إلى نتيجة الأولى. لا يعادل إنشاء مهام Task غير منظمة التزامن المنظم؛ إذ يجب إدارة المقابض والإلغاء مستقلة. أبق المدخلات صغيرة وآمنة للنقل بين حدود العزل. وينبغي لتشخيص Sendable أن يدفع إلى مراجعة الملكية لا إضافة تعليق غير متحقق منه لإسكات المترجم.
انتظر نتائج مصطنعة مستقلة
يجمع المقتطف الأول دالتين محليتين غير متزامنتين. تعبّر async let عن استقلال التسميتين؛ ويجمع انتظار الزوج القيمتين بترتيب نتيجة مختار. لذلك يكون الترتيب Maps ثم Rivers حتى لو اكتملت العمليتان بترتيب آخر. توضح الدالتان الفورية البنية لا تسريعا مقاسا. ويتطلب استبدالهما بإدخال وإخراج حقيقي سياسة فشل وإلغاء وموارد مستقلة. يحذف المقتطف نقطة دخول التطبيق عمدا ولا يدعي تشغيل مترجم Swift أثناء التأليف.
func firstLabel() async -> String { "Maps" }
func secondLabel() async -> String { "Rivers" }
func combinedLabels() async -> String {
async let first = firstLabel()
async let second = secondLabel()
let values = await (first, second)
return "\(values.0), \(values.1)"
}
// await combinedLabels() -> "Maps, Rivers"
Maps, Rivers
ترتيب الزوج محدد، ولا يُدّعى ترتيب جدولة أو تنفيذ متواز فعلي.
يتطلب الإلغاء تعاونا
يضع الإلغاء علامة على المهمة ولا يوقف تعليمات اعتباطية بالقوة. يفحص المقتطف الثاني الإلغاء قبل العمل وبعد نوم يتيح التعليق. وقد ترمي Task.sleep خطأ عند الإلغاء، لذا يحفظ تمريره سياسة المستدعي. لا تلتقطه وتواصل كأن العملية نجحت إلا إذا قصدت ذلك ووثقته. وتحتاج الحلقات الطويلة إلى نقاط فحص مناسبة أو تصميم إلغاء آخر. أما الأمر البعيد فلا يثبت إلغاء الانتظار المحلي أن الخادم تراجع عن تغيير قبله.
func delayedLabel() async throws -> String {
try Task.checkCancellation()
try await Task.sleep(nanoseconds: 1_000_000)
try Task.checkCancellation()
return "Maps"
}
// A non-cancelled caller receives "Maps".
// A cooperating cancelled operation throws instead of publishing a label.
A non-cancelled call returns Maps; cancellation follows the throwing path.
التأخير فترة مصطنعة صغيرة وليس توصية إعادة أو تأكيدا زمنيا. لم تُنفذ مهمة.
اربط المهام بعمر صريح
قد تربط معدلات task في SwiftUI العمل بنشاط العرض وتعيده عند تغير مدخل محدد الهوية. وتظل إشارة الإلغاء بحاجة إلى تعاون العملية. وللمهمة المحفوظة في نموذج مالك آخر وقد تعيش عمدا بعد عرض واحد. حدّد النطاق الذي ينشئ المقبض ويلغيه ويستهلك النتيجة. لا تستخدم مهمة detached مهربا روتينيا من أخطاء الممثل؛ فهي تغير الوراثة ومتطلبات النقل. افصل الإلغاء ورفض النتائج القديمة وعرض الخطأ كي لا ينشر انتهاء شاشة نتيجة في تفاعل جديد.
اختبر الإلغاء عند حدود مضبوطة
استخدم عملية مزيفة تتوقف عند نقطة معروفة ثم ألغ مالكها وحررها وافحص النتيجة الموثقة. لا تجعل النوم الحقيقي الدليل الوحيد على الإلغاء. اختبر النتيجة العادية والفشل والإلغاء قبل البدء وأثناء الانتظار. ولمهمة واجهة افحص مستقلا أن المغادرة وتغير المدخل يمنعان اعتماد حالة قديمة. تبقى نتائج الدورة توضيحية لغياب Swift وXcode. ولا يثبت اختبار إلغاء نقي في بيئة أخرى التنفيذ الخلفي للجهاز أو تراجع الخادم.
الأخطاء الشائعة وإصلاحها
تظل دالة async تعيق التفاعل
- لماذا يحدث؟
- اعتُبر العمل الحسابي المتزامن خلفيا تلقائيا.
- كيف تصلحه؟
- افحص العزل وقِس العمل المكلف قبل اختيار التزامن.
- كيف تتجنب تكراره؟
- افصل التعليق عن التوازي في الشرح.
ينشر العمل الملغى نجاحا
- لماذا يحدث؟
- تُجاهل الإلغاء أو ابتُلع خطؤه.
- كيف تصلحه؟
- افحص الإلغاء واحفظ سياسة تمرير الخطأ.
- كيف تتجنب تكراره؟
- اختبر مسار إلغاء مضبوطا.
تخفي المهام المنفصلة تحذيرات النقل
- لماذا يحدث؟
- استُعمل إنشاء مهمة بدلا من حل الملكية والعزل.
- كيف تصلحه؟
- اختر مالكا صريحا وانقل قيما آمنة بين الحدود.
- كيف تتجنب تكراره؟
- راجع تشخيص Sendable كدليل تصميم.
اختبر فهمك
1. هل يثبت إلغاء المهمة أن الحجز البعيد لم يُحفظ؟
اعرض الحل المشروح
لا. قد يوقف العمل المحلي أو يهمله بينما قبل الخادم الأمر بالفعل. احفظ معرّف عملية وسوِّ الاكتمال غير المؤكد بحسب عقد الخدمة. ليست نتيجة الإلغاء المحلي ضمان تراجع معاملة.
2. متى تبقى عمليتان غير متزامنتين متسلسلتين؟
اعرض الحل المشروح
حين تحتاج الثانية إلى قيمة أو قرار تفويض أو أثر أنتجته الأولى. يخالف بدء كليهما بـ async let هذا الاعتماد. عبّر بالتزامن عن العمل المستقل فعلا وأظهر ترتيب النتيجة المتوقع.
أهم ما تعلمته
- تصف async التعليق لا خيطا خلفيا
- اختبر الإلغاء عند حدود مضبوطة