SwiftUI Series 05|الاستخدام الصحيح لـ NavigationStack والقفز بالصفحة
الأمر الصعب حقًا هو الحفاظ على اتساق حالة التنقل مع حالة العمل، وعدم إفساد التوجيه بالنقرات المتفرقة.
عند استخدام NavigationStack لأول مرة، ستعتقد أنه إصدار SwiftUI من حاوية التنقل:
- انقر
- ادفع الصفحة
- هذا إلى حد كبير
لكن في المشاريع الحقيقية، دائمًا ما يكون الجزء المزعج الحقيقي من التنقل هو:
- سوف تقفز الصفحة
- ما إذا كانت حالة القفزة وحالة العمل متسقتين
- ما إذا كان المسار لا يزال صحيحًا عند الارتباط العميق بالصفحة والعودة إليها وإعادة الدخول إليها
بمعنى آخر، ما يتعين على NavigationStack التعامل معه ليس فقط تبديل الواجهة، بل حالة التنقل نفسها.
1. جاءت مشاكل التنقل في العديد من المشاريع في الماضي بشكل أساسي من “إجراءات القفز المنتشرة في كل مكان”
في عصر UIKit، هناك طريقة شائعة جدًا للكتابة وهي:
- اضغط مباشرة على زر
- تقديم مباشرة في رد الاتصال
- عندما يتصل ViewModel مرة أخرى، فإنه ينتقل عبر المفوض
بالطبع سيعمل هذا على المدى القصير، لكن المشكلة تكمن في أن منطق التنقل سيصبح متناثرًا أكثر فأكثر. من الصعب الإجابة:
- لماذا أنت في هذه الصفحة؟
- ما هي الحالة التي يجب أن تعود إليها بعد العودة؟
- بعد الانتهاء من عمل معين، فإنه سوف يقفز إلى مستويين.
يوفر NavigationStack الخاص بـ SwiftUI فرصة أفضل:
قم بتغيير “مسار التنقل الحالي” من الإجراء الضمني إلى الحالة الصريحة.
2. أهم شيء في NavigationStack هو المسار
عندما تعلمت هذا الجزء من المحتوى NavigationStack لأول مرة، حدقت للتو في:
NavigationLink-navigationDestination
بالطبع أنت بحاجة إلى معرفة هذه الأمور، ولكن ما يجب فهمه أولاً هو:
يمكن التعبير عن التنقل كمسار حالة في SwiftUI.
وهذا يعني لم يعد مجرد “القفز عند النقر”، ولكن الحفاظ على:
- ما هي الصفحات الموجودة في المسار الحالي؟
- ما هي حالة العمل التي تتوافق مع أي وجهة
- كيف يجب أن يتغير المسار بعد عملية معينة؟
بمجرد عرضه من هذا المنظور، يتوقف التنقل عن كونه مجرد حدث لواجهة المستخدم ويبدأ في أن يصبح جزءًا من تدفق الحالة.
3. يتم العبث بالعديد من عمليات التنقل بسبب عدم توافق حالة العمل وحالة التوجيه.
لإعطاء مثال شائع جدا:
- يختار المستخدم مقالا
- يجب أن تظهر صفحة تفاصيل المقالة
- كيفية الخروج من صفحة التفاصيل بعد حذف المقال؟
إذا كنت تفهم التنقل على أنه “انقر للدخول”، فستبدأ العديد من الأسئلة اللاحقة في الارتباك:
- كيفية استعادة المسار عند ظهور رابط عميق
- كيفية ضبط المسار بعد فشل البيانات
- ما هي الحالة التي يجب أن تبقى عليها القائمة عند إعادتها
لذا فإن الشيء الصعب حقًا فيما يتعلق بالملاحة هو أنها لا ينبغي أن توجد بشكل مستقل عن حالة الأعمال.
الفكرة الأكثر استقرارًا هي:
- يمكن تفسير مسار التنقل وحالة العمل بشكل متبادل
- سبب تواجدك حاليًا في هذه الصفحة يمكن تفسيره بوضوح من الحالة.
4. NavigationLink مريح للغاية، ولكن بمجرد أن يصبح المشروع معقدًا، لا يمكنك الاعتماد عليه للتعبير عن التنقل بالكامل
NavigationLink مناسب بشكل خاص للقفزات المباشرة والجزئية والبسيطة، مثل:
- انقر على القائمة للحصول على التفاصيل
- ضبط إعدادات تغذية الصفحة
ولكن إذا كان المشروع معقدًا، وإذا كان كل التنقل يعتمد على NavigationLink المتناثرة، فسوف تواجه قريبًا:
- من الصعب إدارة المسارات بشكل موحد
- يصعب الوصول إلى الروابط العميقة
- لم تعد قفزات العمليات المحددة تعتمد على النقر فحسب.
- مسار العودة منفصل عن حالة العمل
وهذا هو السبب في أنه أكثر ملاءمة للتعامل مع المداخل المحلية وغير مناسب لتنفيذ استراتيجية التنقل للتطبيق بأكمله بمفرده.
5. فكرة أكثر عملية: تصميم “وجهة الصفحة” كقيمة يمكن تفسيرها بواسطة الشركة
أحد الأسباب الجذرية للعديد من حوادث الملاحة في المشروع هو:
- تتم كتابة القفزات كمجموعة من إجراءات واجهة المستخدم
- لم يتم تشكيل نموذج وجهة معقول
الطريقة الأكثر استقرارًا عادةً هي السماح للمسار بأن يحمل “الوجهة التي تريد الشركة الحالية الذهاب إليها.”
على سبيل المثال:
- تفاصيل المقالة (المعرف: سلسلة)
- ملف تعريف المستخدم (المعرف: سلسلة)
- الإعدادات
بهذه الطريقة يبدو التنقل أشبه بالحالات وليس مجموعة مفككة من الإجراءات. فوائدها هي:
- يمكن إعادة بناء المسارات
- الروابط العميقة أكثر طبيعية
- من السهل أيضًا وصف الاختبار وتصحيح الأخطاء
6. الرائحة الكريهة الأكثر شيوعًا في المشاريع الحقيقية: تتشابك إجراءات العرض وViewModel والتوجيه مع بعضها البعض
ينتهي الأمر بالكثير من تعليمات التنقل الخاصة بـ SwiftUI بالشكل التالي:
- اكتب جزءًا من
NavigationLinkفي العرض - قرر ViewModel سرًا القفز مرة أخرى
- يؤدي رد اتصال خدمة معينة إلى تغيير حالة التنقل
وفي النهاية لا يستطيع أحد أن يقول بوضوح:
- من هو المالك الحقيقي للملاحة
- ما هي الحالة التي تحدد المسار الحالي
- هل يعتبر إجراء إرجاع معين سلوكًا للمستخدم أم سلوكًا تجاريًا؟
بمجرد وصول التنقل إلى هذه الحالة، ستزداد تكلفة إضافة رابط عميق أو إضافة مسار استرداد بشكل كبير.
7. حكم عملي: هل الصفحة الحالية “لأنني قمت بالنقر فوق” أو “لأن الحالة تحدد أنها يجب أن تكون هنا”
هذا شيء كثيرا ما أسأل نفسي.
إذا ظهرت صفحة، فلا يمكن تفسيرها إلا على النحو التالي:
- لأنني فقط قمت بالنقر على زر
وهذا يعني عادةً أن التنقل لا يزال يعتمد على الإجراءات بشكل كبير.
التفسير الأكثر مثالية يجب أن يكون:
- لأن حالة المسار الحالية تحتوي عليه
- لأن سياق العمل الحالي يفرض ضرورة عرضه
هذا الاختلاف مهم. الأول أشبه بإجراء مؤقت، والأخير أشبه بحالة تنقل قابلة للصيانة.
8. الخلاصة: ما يسمح نظام NavigationStack بإدارته ليس فقط القفزات، بل حالة المسار.
ولكي أختصر الأمر أقول:
NavigationStackالشيء المهم حقًا هو أنه يسمح بإغلاق التنقل بشكل طبيعي أكثر من “إجراءات النقر المتناثرة” إلى “حالة المسار التي يمكن التحكم فيها”.
لذلك، فإن الطريقة الصحيحة لفتح قفزة الصفحة ليست فقط كتابة NavigationLink، ولكن السماح لحالة التنقل وحالة العمل بشرح بعضهما البعض.
بهذه الطريقة فقط، لن يصبح التنقل مربكًا أكثر فأكثر مع زيادة تعقيد المشروع.
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