NavigationLink to element sterujący w SwiftUI przeznaczony do przechodzenia na inny ekran w NavigationStack lub NavigationView. Według Apple Developer Documentation, 2024, NavigationLink tworzy przycisk, po kliknięciu którego docelowy View jest umieszczany w stosie nawigacyjnym. W iOS 16+ zaleca się używanie NavigationLink z value i NavigationDestination, a nie bezpośrednio z destination, aby uniknąć przedwczesnej inicjalizacji docelowych View.
Najważniejsze
NavigationLink to View, które po kliknięciu inicjuje przejście nawigacyjne. Wewnątrz NavigationStack kliknięcie NavigationLink umieszcza docelowy ekran na stosie i wyświetla systemowy przycisk „Wstecz”. NavigationLink istnieje od iOS 13 i jest podstawowym sposobem nawigacji użytkownika w SwiftUI.
NavigationLink nie dziedziczy po UIButton — to View SwiftUI, które automatycznie dostosowuje się do kontekstu. Wewnątrz List NavigationLink wyświetla się ze strzałką ujawniania (disclosure indicator). Poza listą NavigationLink zachowuje się jak zwykły przycisk, ale z zachowaniem nawigacyjnym.
Według SwiftUI Lab (2024), NavigationLink jest jednym z najczęściej używanych View w aplikacjach SwiftUI, ustępując tylko Text, Image i VStack. Zrozumienie różnic między formami inicjalizacji jest kluczowe dla wydajności i przewidywalnego zachowania nawigacji.
Po kliknięciu NavigationLink dodaje wartość (lub destination) do stosu nawigacyjnego powiązanego z najbliższym NavigationStack lub NavigationView. SwiftUI używa EnvironmentValue do przekazywania ścieżki nawigacji przez hierarchię View. NavigationLink odczytuje tę ścieżkę z Environment i po kliknięciu ją modyfikuje.
NavigationLink ma dwie główne formy: z destination (bezpośrednie wskazanie docelowego View) i z value (wartość dla NavigationDestination). Wybór formy zależy od wersji iOS i architektury nawigacji.
| Forma | Inicjalizator | iOS 13–15 | iOS 16+ |
|---|---|---|---|
| Destination | NavigationLink(destination:label:) | Zalecana | Nie zalecana |
| Value | NavigationLink(value:label:) | Niedostępna | Zalecana |
| IsActive | NavigationLink(isActive:destination:label:) | Nawigacja programowa | Nie zalecana |
Forma Destination (iOS 13+): NavigationLink(destination: DetailView(), label: { Text("Open") }). Ta forma tworzy DetailView od razu podczas renderowania NavigationLink, nawet jeśli użytkownik nie kliknął linku. Prowadzi to do przedwczesnej inicjalizacji View i potencjalnych problemów z wydajnością, jeśli docelowe View wykonuje ciężkie operacje w inicjalizatorze.
Forma Value (iOS 16+): NavigationLink(value: "detail_42", label: { Text("Open") }). Docelowe View jest tworzone tylko po kliknięciu linku, gdy SwiftUI znajdzie odpowiedni .navigationDestination. Zapobiega to przedwczesnej inicjalizacji i czyni nawigację bardziej przewidywalną.
NavigationLink z NavigationStack w iOS 16+ wymaga przejścia na formę value. Definiujesz typ danych dla nawigacji (String, Int, enum Route) i rejestrujesz destination przez .navigationDestination. NavigationLink umieszcza w stosie tylko wartość, a SwiftUI tworzy docelowe View po kliknięciu.
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)
}
}
}
// Nawigacja programowa:
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("Otwórz ustawienia") {
path.append(AppRoute.settings)
}
}
}
}
}
Nawigacja programowa: dodanie wartości do path (przez path.append) jest równoważne kliknięciu NavigationLink z tą samą wartością. Umożliwia to implementację nawigacji z ViewModel, Coordinator lub w odpowiedzi na powiadomienia push.
Forma IsActive (NavigationLink(isActive:destination:label:)) jest dostępna dla zgodności, ale nie jest zalecana w iOS 16+. Używaj formy value z Binding do tablicy ścieżki lub NavigationPath.
NavigationLink w List automatycznie wyświetla strzałkę ujawniania (chevron) w prawej części wiersza, sygnalizując użytkownikowi, że kliknięcie doprowadzi do przejścia na inny ekran. List zarządza wyświetlaniem strzałki automatycznie — w przeciwieństwie do zwykłego NavigationLink poza listą, gdzie strzałki nie ma.
Od iOS 16 List z NavigationLink automatycznie używa formy value wewnątrz List(data:rowContent:). Przy użyciu ForEach wewnątrz List strzałka ujawniania również jest dodawana automatycznie. Tego zachowania nie można wyłączyć przez modyfikatory — tylko zastąpienie NavigationLink na Button może usunąć strzałkę.
Problem z formą destination w List: jeśli używasz NavigationLink(destination:label:) wewnątrz List, wszystkie docelowe View są tworzone od razu podczas ładowania listy, niezależnie od tego, czy użytkownik kliknął link, czy nie. Dla list z dużą liczbą wierszy może to znacząco spowolnić początkowe ładowanie i zwiększyć zużycie pamięci. Forma value z NavigationStack rozwiązuje ten problem.
Według WWDC 2022 (Session 10054), Apple zaleca używanie NavigationStack i formy value NavigationLink dla nowych projektów. Jest to szczególnie ważne dla List z dynamicznymi danymi, gdzie liczba wierszy może być duża.
Wzorzec 1: niestandardowy wygląd NavigationLink. NavigationLink przyjmuje dowolne View jako label, umożliwiając tworzenie dowolnego projektu linku. Wewnątrz List jest to szczególnie wygodne — otrzymujesz strzałkę ujawniania automatycznie przy użyciu 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)
}
Wzorzec 2: NavigationLink bez strzałki (niestandardowy przycisk). Jeśli nie potrzebujesz strzałki ujawniania, użyj Button do nawigacji programowej: path.append(value). Jest to przydatne dla niestandardowych elementów interfejsu, gdzie NavigationLink wygląda nienaturalnie.
Wzorzec 3: nawigacja warunkowa. Możesz zablokować NavigationLink, używając pustego destination lub nie dodając .navigationDestination dla określonych wartości. Nawigacja programowa przez path pozwala sprawdzać warunki przed dodaniem wartości.
Według Hacking with Swift (2024), większość problemów z NavigationLink związana jest z używaniem formy destination w starszych projektach. Podczas migracji na NavigationStack zamień wszystkie NavigationLink(destination:label:) na NavigationLink(value:label:) i dodaj .navigationDestination na poziomie głównym.
Często zadawane pytania
NavigationLink to View do przechodzenia na inny ekran w SwiftUI. Po kliknięciu umieszcza docelowy ekran w stosie nawigacyjnym NavigationStack lub NavigationView. Obsługuje dwie formy: z destination (docelowym View) i z value (wartością do routingu).
Forma Value (iOS 16+) jest preferowana: docelowe View jest tworzone tylko po kliknięciu, a nie podczas renderowania linku. Forma Destination tworzy View od razu, co może powodować problemy z wydajnością. Dla projektów z iOS 16+ używaj value + NavigationDestination.
SwiftUI automatycznie dodaje disclosure indicator (strzałkę) do NavigationLink wewnątrz List, sygnalizując możliwość przejścia. Tego zachowania nie można wyłączyć. Jeśli strzałka nie jest potrzebna, użyj Button z nawigacją programową przez path.append().
Użyj NavigationStack z Binding ścieżką i dodawaj wartości przez path.append(value). Jest to równoważne kliknięciu NavigationLink z tą samą wartością. Nawigacja programowa umożliwia implementację Deeplinków, powiadomień push i wzorca Coordinator.
Forma Destination może wpływać, jeśli docelowe View wykonują ciężkie operacje w inicjalizatorze — wszystkie destination są tworzone podczas renderowania listy. Forma Value z NavigationStack rozwiązuje ten problem, tworząc View tylko po kliknięciu. Dla list z 50+ wierszami różnica jest znacząca.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również