Как работает NavigationStack и NavigationPath в SwiftUI 4+

С выходом iOS 16 Apple представила новую систему навигации в SwiftUI - NavigationStack и NavigationPath. Эти компоненты пришли на смену устаревшему NavigationView и предлагают более гибкий и мощный способ управления навигацией в приложениях. В этой статье мы разберём, как работает новая система навигации и как её эффективно использовать.


Основные понятия

NavigationStack

NavigationStack - это новый контейнер для навигации, который управляет стеком представлений. В отличие от старого NavigationView, он предоставляет более предсказуемое поведение и лучший контроль над навигацией.

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Детали", value: "details")
                NavigationLink("Настройки", value: "settings")
            }
            .navigationDestination(for: String.self) { value in
                switch value {
                case "details":
                    DetailsView()
                case "settings":
                    SettingsView()
                default:
                    EmptyView()
                }
            }
        }
    }
}

NavigationPath

NavigationPath - это тип, который представляет собой стек навигации. Он позволяет программно управлять навигацией и сохранять состояние стека.

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

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Button("Перейти к деталям") {
                    path.append("details")
                }
                Button("Перейти к настройкам") {
                    path.append("settings")
                }
            }
            .navigationDestination(for: String.self) { value in
                switch value {
                case "details":
                    DetailsView()
                case "settings":
                    SettingsView()
                default:
                    EmptyView()
                }
            }
        }
    }
}

Типы навигации

Типизированная навигация

SwiftUI 4+ позволяет использовать типизированную навигацию, что делает код более безопасным и предсказуемым.

enum Route: Hashable {
    case details(id: String)
    case settings
    case profile(userId: Int)
}

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

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Button("Детали") {
                    path.append(Route.details(id: "123"))
                }
                Button("Настройки") {
                    path.append(Route.settings)
                }
                Button("Профиль") {
                    path.append(Route.profile(userId: 1))
                }
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .details(let id):
                    DetailsView(id: id)
                case .settings:
                    SettingsView()
                case .profile(let userId):
                    ProfileView(userId: userId)
                }
            }
        }
    }
}

Глубокая навигация

Новая система позволяет легко реализовать глубокую навигацию и программное управление стеком.

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

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Button("Глубокая навигация") {
                    // Добавляем несколько экранов в стек
                    path.append("screen1")
                    path.append("screen2")
                    path.append("screen3")
                }
            }
            .navigationDestination(for: String.self) { screen in
                switch screen {
                case "screen1":
                    Screen1View()
                case "screen2":
                    Screen2View()
                case "screen3":
                    Screen3View()
                default:
                    EmptyView()
                }
            }
        }
    }
}

Практические примеры

Передача данных между экранами

struct User: Identifiable, Hashable {
    let id: Int
    let name: String
}

struct UserListView: View {
    @State private var path = NavigationPath()
    let users = [User(id: 1, name: "Иван"), User(id: 2, name: "Петр")]

    var body: some View {
        NavigationStack(path: $path) {
            List(users) { user in
                NavigationLink(value: user) {
                    Text(user.name)
                }
            }
            .navigationDestination(for: User.self) { user in
                UserDetailView(user: user)
            }
        }
    }
}

Управление состоянием навигации

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

    var body: some View {
        NavigationStack(path: $path) {
            List {
                Button("Сбросить навигацию") {
                    path.removeLast(path.count)
                }
                Button("Вернуться на шаг назад") {
                    path.removeLast()
                }
                Button("Добавить экран") {
                    path.append("newScreen")
                }
            }
            .navigationDestination(for: String.self) { screen in
                Text("Экран: (screen)")
            }
        }
    }
}

Заключение

Новая система навигации в SwiftUI 4+ предоставляет разработчикам мощные инструменты для создания гибкой и предсказуемой навигации. Использование NavigationStack и NavigationPath позволяет создавать более сложные навигационные сценарии и лучше управлять состоянием приложения.


Хотите узнать больше о разработке iOS приложений? Подписывайтесь на наш YouTube канал и скачивайте iJun в App Store для практики!

Также читайте:  Как подключить CoreData к SwiftUI проекту: пошаговое руководство