NavigationStack: що це, навігаційний стек у SwiftUI

Автор: IT Sectr Опубліковано: 2026-06-24 Час читання: 6 хв

NavigationStack — це сучасний навігаційний контейнер у SwiftUI, представлений у iOS 16+ і який замінив NavigationView. Згідно з документацією Apple Developer, 2024, NavigationStack керує стеком екранів через типобезпечний шлях навігації (NavigationPath), підтримує глибоку навігацію, програмне повернення на кореневий екран та збереження стану при зміні даних. На відміну від NavigationView, NavigationStack не потребує обгортання в додатковий контейнер і надає прямий Binding до шляху навігації.

Головне

  • NavigationStack — новий навігаційний контейнер SwiftUI (iOS 16+)
  • NavigationPath — типобезпечний шлях для керування стеком екранів
  • Deep linking — підтримка програмної навігації через шлях
  • NavigationDestination — реєстрація цільових екранів за типами даних
  • Стан навігації зберігається та відновлюється автоматично

Що таке NavigationStack у SwiftUI?

NavigationStack — це контейнерне View, що реалізує навігацію на основі стека (LIFO). Воно керує історією переходів, дозволяючи поміщати нові екрани в стек і повертатися назад через системну кнопку «Назад» або програмно. NavigationStack є частиною SwiftUI, починаючи з iOS 16, iPadOS 16, macOS 13, watchOS 9 та tvOS 16.

Основне нововведення NavigationStack — типобезпечний шлях навігації. Замість прямого вказання destination при створенні NavigationLink, ви поміщаєте в шлях значення (value), а реєстрація цільового View відбувається окремо через модифікатор .navigationDestination(for:destination:). Це розділяє навігацію та відображення, роблячи код більш модульним і тестованим.

Згідно з WWDC 2022 (Сесія 10054), NavigationStack використовує новий механізм навігації, заснований на ObservableObject та SwiftUI lifecycle. На відміну від NavigationView, який покладався на UINavigationController всередині, NavigationStack повністю реалізований на SwiftUI, що покращує передбачуваність і сумісність із SwiftUI lifecycle.

Базова структура NavigationStack

NavigationStack приймає кореневе View та опціональний шлях навігації (Binding до NavigationPath або масиву Hashable значень). Усі дочірні екрани поміщаються в стек через NavigationLink або програмне додавання значень у шлях.

NavigationView був основним навігаційним контейнером SwiftUI до iOS 16. Він автоматично керував UINavigationController всередині, що призводило до низки проблем: непередбачувана поведінка при зміні даних, складність із програмною навігацією та відсутність типобезпеки.

ХарактеристикаNavigationStack (iOS 16+)NavigationView (iOS 13–15)
Тип навігаціїСтек (LIFO)Стек (LIFO)
Шлях навігаціїТипізований (NavigationPath)Не підтримується
Deep linkingВбудована підтримкаПотребує хаків
Програмне поверненняЧерез шлях (pop, popToRoot)dismiss, presentationMode
ВсерединіSwiftUI нативнийUINavigationController
СумісністьiOS 16+iOS 13+

Ключова перевага NavigationStack — типобезпечна навігація. Ви визначаєте шлях як масив конкретних типів (або NavigationPath для гетерогенних стеків) і реєструєте destination для кожного типу. Це виключає помилки невідповідності типів і робить навігацію передбачуваною.

NavigationView deprecated в iOS 17. Apple рекомендує мігрувати на NavigationStack для всіх нових проектів і при оновленні мінімальної версії до iOS 16.

NavigationPath — це тип, що представляє шлях навігації в NavigationStack. Він може зберігати гетерогенні значення (AnyHashable) або використовуватися з конкретним типом через Binding до масиву [T: Hashable]. NavigationPath автоматично кодується та декодується для збереження стану.

swift
struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: String.self) { value in
                    DetailView(id: value)
                }
                .navigationDestination(for: Int.self) { value in
                    NumberView(number: value)
                }
        }
    }

    func goToRoot() {
        path.removeLast(path.count)
    }

    func pushDeepLink() {
        path.append("detail_42")
    }
}

Гетерогенний стек: NavigationPath може містити значення різних типів, якщо вони реалізують Hashable. Наприклад, перший екран може приймати String (ID), другий — Int (номер), третій — кастомний enum Route. Для відображення кожного типу реєструється окремий .navigationDestination.

Codable підтримка: NavigationPath реалізує Codable, якщо всі значення в шляху також Codable + Hashable. Це дозволяє зберігати та відновлювати стан навігації при перезапуску програми або при переході у фоновий режим.

.navigationDestination(for:destination:) — модифікатор, що реєструє цільове View для конкретного типу даних. Коли NavigationLink поміщає в шлях значення цього типу, SwiftUI автоматично знаходить відповідний .navigationDestination і створює екран.

swift
enum AppRoute: Hashable {
    case profile(UserID)
    case settings
    case about
}

struct AppNavigation: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: AppRoute.self) { route in
                    switch route {
                    case .profile(let id):
                        ProfileView(userId: id)
                    case .settings:
                        SettingsView()
                    case .about:
                        AboutView()
                    }
                }
        }
    }
}

// Navigate: path.append(AppRoute.profile("user_123"))

Важливе правило: .navigationDestination повинен бути застосований до View, яке знаходиться всередині NavigationStack, і до того, як NavigationLink помістить значення в шлях. Зазвичай його додають до кореневого View або до контейнера секції. Якщо .navigationDestination не знайдено для типу значення, перехід не відбудеться.

Згідно з SwiftUI Engineering (2023), .navigationDestination може бути зареєстрований на різних рівнях ієрархії. SwiftUI шукає найближчий відповідний destination при спробі навігації. Це дозволяє перевизначати destination для одного типу в різних частинах програми.

Паттерн 1: навігація через enum Route. Визначте enum з асоційованими значеннями для всіх екранів програми. Використовуйте один .navigationDestination для AppRoute та switch для маршрутизації. Це забезпечує єдине джерело істини для всіх можливих переходів у програмі.

swift
struct StoreView: View {
    @State private var path: [ProductRoute] = []

    var body: some View {
        NavigationStack(path: $path) {
            ProductGrid()
                .navigationDestination(for: ProductRoute.self) { route in
                    switch route {
                    case .detail(let product):
                        ProductDetail(product: product)
                    case .reviews(let productId):
                        ReviewsView(productId: productId)
                    }
                }
        }
    }
}

enum ProductRoute: Hashable {
    case detail(Product)
    case reviews(String)
}

Паттерн 2: програмна навігація та deep linking. NavigationStack дозволяє програмно керувати стеком: додавати, видаляти екрани та повертатися на корінь. Це необхідно для push-сповіщень, deep link-ів та відновлення навігації після перезапуску.

Паттерн 3: масив типів замість NavigationPath. Якщо всі екрани використовують один тип (наприклад, String або кастомний enum), використовуйте Binding до [T]. Це дає більш сувору типізацію та кращу продуктивність, ніж NavigationPath. NavigationPath виправданий для гетерогенних стеків із різними типами екранів.

Згідно з Point-Free (2024), NavigationStack з enum Route — найкращий спосіб організації навігації в SwiftUI-додатках. Він робить всі можливі переходи явними, типобезпечними та тестованими, що особливо важливо для великих проектів із десятками екранів.

Часті запитання

Що таке NavigationStack у SwiftUI?

NavigationStack — навігаційний контейнер SwiftUI (iOS 16+), що керує стеком екранів через типобезпечний шлях. Замінив NavigationView, пропонуючи підтримку deep linking, програмної навігації та збереження стану.

Чим NavigationStack відрізняється від NavigationView?

NavigationStack використовує типобезпечний шлях (NavigationPath) замість прямого зв'язування NavigationLink з destination. Підтримує програмну навігацію, deep linking та Codable для збереження стану. Працює на SwiftUI, а не через UINavigationController.

Як працює NavigationPath?

NavigationPath — це тип, що представляє послідовність екранів у стеку. Ви додаєте значення в шлях через path.append() або через NavigationLink з value. Для відображення кожного типу реєструється .navigationDestination. NavigationPath підтримує Codable та автоматичне збереження стану.

Як реалізувати deep linking з NavigationStack?

Через програмне керування шляхом: після обробки URL викликайте path.append() з відповідним значенням маршруту. NavigationStack автоматично відобразить цільовий екран. Повернення на корінь — path.removeLast(path.count).

Чи потрібно мігрувати з NavigationView на NavigationStack?

Так, якщо ваша мінімальна версія iOS 16+. NavigationView deprecated в iOS 17. Міграція дає типобезпечну навігацію, підтримку deep linking та кращу відповідність SwiftUI lifecycle. Для проектів з iOS 15 і нижче поки використовуйте NavigationView.

Підсумки

  • NavigationStack — сучасний навігаційний контейнер SwiftUI (iOS 16+)
  • NavigationPath — типобезпечний шлях для керування стеком екранів
  • NavigationDestination — реєстрація цільових View за типами даних
  • NavigationView deprecated в iOS 17, міграція рекомендована
  • Deep linking та програмна навігація — вбудована підтримка
  • Enum Route — найкращий паттерн для організації навігації
  • Гетерогенний стек через NavigationPath з будь-якими Hashable типами

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також