NavigationLink — что это, кнопка перехода в SwiftUI

Автор: IT Sectr Опубликовано: 2026-06-25 Время чтения: 6 мин

NavigationLink — это элемент управления в SwiftUI, предназначенный для перехода на другой экран в NavigationStack или NavigationView. По данным Apple Developer Documentation, 2024, NavigationLink создаёт кнопку, при нажатии на которую целевой View помещается в навигационный стек. В iOS 16+ рекомендуется использовать NavigationLink с value и NavigationDestination, а не с destination напрямую, чтобы избежать преждевременной инициализации целевых View.

Главное

  • NavigationLink — кнопка перехода на другой экран в SwiftUI
  • Две формы — с destination:label: и с value:label:
  • Value-форма рекомендована в iOS 16+ (NavigationStack)
  • Destination-форма приводит к преждевременной инициализации View
  • Автоматическая стрелка раскрытия в списках List

NavigationLink — это View, которое при нажатии инициирует навигационный переход. Внутри NavigationStack нажатие на NavigationLink помещает целевой экран на стек и отображает системную кнопку «Назад». NavigationLink существует с iOS 13 и является основным способом пользовательской навигации в SwiftUI.

NavigationLink не наследуется от UIButton — это SwiftUI View, которое автоматически адаптируется к контексту. Внутри List NavigationLink отображается со стрелкой раскрытия (disclosure indicator). Вне списка NavigationLink ведёт себя как обычная кнопка, но с навигационным поведением.

По данным SwiftUI Lab (2024), NavigationLink является одной из самых используемых View в SwiftUI-приложениях, уступая только Text, Image и VStack. Понимание различий между формами инициализации критически важно для производительности и предсказуемого поведения навигации.

Как работает NavigationLink под капотом

При нажатии NavigationLink добавляет значение (или destination) в навигационный стек, связанный с ближайшим NavigationStack или NavigationView. SwiftUI использует EnvironmentValue для передачи пути навигации через иерархию View. NavigationLink читает этот путь из Environment и при нажатии модифицирует его.

NavigationLink имеет две основные формы: с destination (прямое указание целевого View) и с value (значение для NavigationDestination). Выбор формы зависит от версии iOS и архитектуры навигации.

ФормаИнициализаторiOS 13–15iOS 16+
DestinationNavigationLink(destination:label:)РекомендуетсяНе рекомендуется
ValueNavigationLink(value:label:)НедоступнаРекомендуется
IsActiveNavigationLink(isActive:destination:label:)Программная навигацияНе рекомендуется

Destination-форма (iOS 13+): NavigationLink(destination: DetailView(), label: { Text("Open") }). Эта форма создаёт DetailView сразу при рендеринге NavigationLink, даже если пользователь не нажал на ссылку. Это приводит к преждевременной инициализации View и потенциальным проблемам с производительностью, если destination View выполняет тяжёлые операции в инициализаторе.

Value-форма (iOS 16+): NavigationLink(value: "detail_42", label: { Text("Open") }). Целевой View создаётся только при нажатии на ссылку, когда SwiftUI находит соответствующий .navigationDestination. Это предотвращает преждевременную инициализацию и делает навигацию более предсказуемой.

NavigationLink с NavigationStack в iOS 16+ требует перехода на value-форму. Вы определяете тип данных для навигации (String, Int, enum Route) и регистрируете destination через .navigationDestination. NavigationLink помещает в стек только значение, а SwiftUI создаёт целевое View при нажатии.

swift
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 (через path.append) эквивалентно нажатию NavigationLink с таким же значением. Это позволяет реализовать навигацию из ViewModel, Coordinator или в ответ на push-уведомления.

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, все destination View создаются сразу при загрузке списка, независимо от того, нажал пользователь на ссылку или нет. Для списков с большим количеством строк это может существенно замедлить начальную загрузку и увеличить потребление памяти. Value-форма с NavigationStack решает эту проблему.

По данным WWDC 2022 (Session 10054), Apple рекомендует использовать NavigationStack и value-форму NavigationLink для новых проектов. Это особенно важно для List с динамическими данными, где количество строк может быть большим.

Паттерн 1: кастомный вид NavigationLink. NavigationLink принимает любое View в качестве label, позволяя создавать произвольный дизайн для ссылки. Внутри List это особенно удобно — вы получаете стрелку раскрытия автоматически при использовании NavigationLink.

swift
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 для определённых значений. Программная навигация через path позволяет проверять условия перед добавлением значения.

По данным Hacking with Swift (2024), большинство проблем с NavigationLink связано с использованием destination-формы в старых проектах. При миграции на NavigationStack замените все NavigationLink(destination:label:) на NavigationLink(value:label:) и добавьте .navigationDestination на корневом уровне.

Часто задаваемые вопросы

Что такое NavigationLink в SwiftUI?

NavigationLink — это View для перехода на другой экран в SwiftUI. При нажатии помещает целевой экран в навигационный стек NavigationStack или NavigationView. Поддерживает две формы: с destination (целевым View) и с value (значением для маршрутизации).

Какая форма NavigationLink лучше: destination или value?

Value-форма (iOS 16+) предпочтительнее: целевой View создаётся только при нажатии, а не при рендеринге ссылки. Destination-форма создаёт View сразу, что может вызывать проблемы с производительностью. Для проектов с iOS 16+ используйте value + NavigationDestination.

Почему NavigationLink создаёт стрелку в List?

SwiftUI автоматически добавляет disclosure indicator (стрелку) к NavigationLink внутри List, сигнализируя о возможности перехода. Это поведение нельзя отключить. Если стрелка не нужна, используйте Button с программной навигацией через path.append().

Как сделать программный переход через NavigationLink?

Используйте NavigationStack с Binding путём и добавляйте значения через path.append(value). Это эквивалентно нажатию NavigationLink с таким же value. Программная навигация позволяет реализовать Deeplink-и, push-уведомления и Coordinator-паттерн.

Влияет ли NavigationLink на производительность?

Destination-форма может влиять, если целевые View выполняют тяжёлые операции в инициализаторе — все destination создаются при рендеринге списка. Value-форма с NavigationStack решает эту проблему, создавая View только при нажатии. Для списков с 50+ строками разница существенна.

Итоги

  • NavigationLink — кнопка для навигационных переходов между экранами SwiftUI
  • Value-форма рекомендована в iOS 16+ с NavigationStack
  • Destination-форма создаёт View преждевременно — избегайте для больших списков
  • Disclosure indicator — автоматическая стрелка в List (не отключается)
  • Программная навигация через path.append() для Deeplink-ов и Coordinator
  • NavigationDestination регистрирует целевые экраны по типам данных
  • IsActive форма — устаревшая, используйте value-форму на iOS 16+

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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