NavigationLink هو عنصر تحكم في SwiftUI مصمم للانتقال إلى شاشة أخرى في NavigationStack أو NavigationView. وفقاً لـ Apple Developer Documentation, 2024، NavigationLink ينشئ زراً عند الضغط عليه يضع View الهدف في مكدس التنقل. في iOS 16+ يُوصى باستخدام NavigationLink مع value و NavigationDestination بدلاً من destination مباشرة لتجنب التهيئة المبكرة لـ View الهدف.
الخلاصة
NavigationLink هو View يبدأ انتقال تنقل عند الضغط عليه. داخل NavigationStack، يؤدي الضغط على NavigationLink إلى وضع الشاشة الهدف في المكدس وعرض زر العودة للنظام. NavigationLink موجود منذ iOS 13 وهو الطريقة الأساسية لتنقل المستخدم في SwiftUI.
NavigationLink لا يرث من UIButton — إنه View في SwiftUI يتكيف تلقائياً مع السياق. داخل List، يظهر NavigationLink مع مؤشر الكشف. خارج القائمة، يتصرف NavigationLink كزر عادي ولكن مع سلوك تنقل.
وفقاً لـ SwiftUI Lab (2024)، NavigationLink هو أحد أكثر Views استخداماً في تطبيقات SwiftUI، يليه فقط Text و Image و VStack. فهم الفروق بين أشكال التهيئة أمر بالغ الأهمية للأداء وسلوك التنقل المتوقع.
عند الضغط، يضيف NavigationLink قيمة (أو destination) إلى مكدس التنقل المرتبط بأقرب NavigationStack أو NavigationView. يستخدم SwiftUI EnvironmentValue لتمرير مسار التنقل عبر تسلسل Views. يقرأ NavigationLink هذا المسار من Environment ويقوم بتعديله عند الضغط.
NavigationLink له شكلان رئيسيان: مع destination (تحديد View الهدف مباشرة) ومع value (قيمة لـ NavigationDestination). يعتمد اختيار الشكل على إصدار iOS وهندسة التنقل.
| الشكل | المُهيئ | iOS 13–15 | iOS 16+ |
|---|---|---|---|
| Destination | NavigationLink(destination:label:) | موصى به | غير موصى به |
| Value | NavigationLink(value:label:) | غير متاح | موصى به |
| IsActive | NavigationLink(isActive:destination:label:) | تنقل برمجي | غير موصى به |
شكل destination (iOS 13+): NavigationLink(destination: DetailView(), label: { Text("Open") }). هذا الشكل ينشئ DetailView فوراً عند عرض NavigationLink، حتى لو لم ينقر المستخدم على الرابط. يؤدي هذا إلى تهيئة مبكرة لـ View ومشاكل محتملة في الأداء إذا كان View الهدف يقوم بعمليات ثقيلة في المُهيئ الخاص به.
شكل value (iOS 16+): NavigationLink(value: "detail_42", label: { Text("Open") }). يتم إنشاء View الهدف فقط عند الضغط على الرابط، عندما يجد SwiftUI .navigationDestination المقابل. هذا يمنع التهيئة المبكرة ويجعل التنقل أكثر قابلية للتنبؤ.
NavigationLink مع NavigationStack في iOS 16+ يتطلب التحول إلى شكل value. يمكنك تحديد نوع بيانات للتنقل (String, Int, enum Route) وتسجيل الوجهة عبر .navigationDestination. NavigationLink يضع القيمة فقط في المكدس، ويقوم SwiftUI بإنشاء View الهدف عند الضغط.
struct CatalogView: View {
let categories: [String]
var body: some View {
List(categories, id: \.self) { category in
NavigationLink(value: category) {
Text(category)
}
}
.navigationDestination(for: String.self) { category in
CategoryView(name: category)
}
}
}
// Programmatic navigation:
struct DeepLinkView: View {
@State private var path: [AppRoute] = []
var body: some View {
NavigationStack(path: $path) {
HomeView()
.navigationDestination(for: AppRoute.self) { route in
switch route {
case .detail(let id): DetailView(id: id)
case .settings: SettingsView()
}
}
.toolbar {
Button("Open Settings") {
path.append(AppRoute.settings)
}
}
}
}
}
التنقل البرمجي: إضافة قيمة إلى المسار (عبر path.append) يعادل الضغط على NavigationLink بنفس القيمة. يتيح ذلك تنفيذ التنقل من ViewModel أو Coordinator أو استجابة لإشعارات الدفع.
شكل IsActive (NavigationLink(isActive:destination:label:)) متاح للتوافق ولكن غير موصى به في iOS 16+. استخدم شكل value مع Binding لمصفوفة مسار أو NavigationPath.
NavigationLink في List يعرض تلقائياً مؤشر كشف (chevron) على الجانب الأيمن من الصف، للإشارة إلى أن الضغط سيؤدي إلى شاشة أخرى. تدير List عرض السهم تلقائياً — على عكس NavigationLink العادي خارج القائمة، حيث لا يوجد سهم.
مع iOS 16، List مع NavigationLink تستخدم تلقائياً شكل value داخل List(data:rowContent:). عند استخدام ForEach داخل List، يتم إضافة مؤشر الكشف أيضاً تلقائياً. لا يمكن تعطيل هذا السلوك من خلال المعدِّلات — فقط استبدال NavigationLink بـ Button يمكنه إزالة السهم.
مشكلة شكل destination في List: إذا كنت تستخدم NavigationLink(destination:label:) داخل List، يتم إنشاء جميع Views الهدف فوراً عند تحميل القائمة، بغض النظر عما إذا كان المستخدم قد نقر على الرابط أم لا. للقوائم التي تحتوي على عدد كبير من الصفوف، يمكن أن يؤدي ذلك إلى إبطاء التحميل الأولي بشكل كبير وزيادة استهلاك الذاكرة. شكل value مع NavigationStack يحل هذه المشكلة.
وفقاً لـ WWDC 2022 (Session 10054)، توصي Apple باستخدام NavigationStack وشكل value من NavigationLink للمشاريع الجديدة. هذا مهم بشكل خاص لـ List ذات البيانات الديناميكية، حيث يمكن أن يكون عدد الصفوف كبيراً.
النمط 1: مظهر مخصص لـ NavigationLink. يقبل NavigationLink أي View كـ label، مما يسمح بإنشاء تصاميم مخصصة للرابط. داخل List، هذا مناسب بشكل خاص — تحصل على مؤشر كشف تلقائي عند استخدام NavigationLink.
NavigationLink(value: ProductRoute.detail(product)) {
HStack {
AsyncImage(url: product.imageURL)
.frame(width: 60, height: 60)
VStack(alignment: .leading) {
Text(product.name).font(.headline)
Text(product.price) .foregroundColor(.secondary)
}
}
.padding(8)
}
النمط 2: NavigationLink بدون سهم (زر مخصص). إذا كنت لا تحتاج إلى مؤشر كشف، استخدم Button للتنقل البرمجي: path.append(value). هذا مفيد لعناصر الواجهة المخصصة حيث يبدو NavigationLink غير طبيعي.
النمط 3: التنقل الشرطي. يمكنك حظر NavigationLink باستخدام destination فارغ أو عدم إضافة .navigationDestination لقيم معينة. يسمح التنقل البرمجي عبر المسار بالتحقق من الشروط قبل إضافة قيمة.
وفقاً لـ Hacking with Swift (2024)، ترتبط معظم مشاكل NavigationLink باستخدام شكل destination في المشاريع القديمة. عند الترحيل إلى NavigationStack، استبدل جميع NavigationLink(destination:label:) بـ NavigationLink(value:label:) وأضف .navigationDestination على المستوى الجذري.
الأسئلة الشائعة
NavigationLink هو View للانتقال إلى شاشة أخرى في SwiftUI. عند الضغط، يضع الشاشة الهدف في مكدس التنقل NavigationStack أو NavigationView. يدعم شكلين: مع destination (View الهدف) ومع value (قيمة التوجيه).
شكل value (iOS 16+) أفضل: يتم إنشاء View الهدف فقط عند الضغط، وليس عند عرض الرابط. شكل destination ينشئ View فوراً، مما قد يسبب مشاكل في الأداء. للمشاريع التي تستخدم iOS 16+، استخدم value + NavigationDestination.
يضيف SwiftUI تلقائياً مؤشر كشف (سهماً) إلى NavigationLink داخل List، للإشارة إلى إمكانية التنقل. لا يمكن تعطيل هذا السلوك. إذا لم يكن السهم مطلوباً، استخدم Button مع التنقل البرمجي عبر path.append().
استخدم NavigationStack مع Binding للمسار وأضف القيم عبر path.append(value). هذا يعادل الضغط على NavigationLink بنفس value. يتيح التنقل البرمجي تنفيذ الروابط العميقة وإشعارات الدفع ونمط Coordinator.
يمكن أن يؤثر شكل destination على الأداء إذا كانت Views الهدف تقوم بعمليات ثقيلة في المُهيئ الخاص بها — يتم إنشاء جميع الوجهات عند عرض القائمة. شكل value مع NavigationStack يحل هذه المشكلة عن طريق إنشاء Views فقط عند الضغط. للقوائم التي تحتوي على 50+ صفاً، الفرق كبير.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.