NavigationView: khái niệm cơ bản, ngăn xếp điều hướng trong ứng dụng SwiftUI

Tác giả: IT Sectr Đã đăng: 2026-02-22 Thời gian đọc: 6 phút

NavigationView là một thành phần vùng chứa SwiftUI để tổ chức điều hướng dạng ngăn xếp giữa các màn hình. NavigationView tạo một ngăn xếp điều hướng với thanh điều hướng tự động, tiêu đề và nút «Quay lại». Kể từ iOS 16, Apple khuyên dùng NavigationStack. Đọc thêm trong tài liệu Apple.

Những điểm chính

  • NavigationView — vùng chứa SwiftUI cho điều hướng ngăn xếp, tạo thanh điều hướng và nút Quay lại
  • NavigationLink — phần tử chuyển tiếp đến màn hình mới bên trong NavigationView
  • NavigationStack — kế thừa của NavigationView (iOS 16+) với quản lý ngăn xếp lập trình
  • .toolbar — bổ trợ để thêm nút vào thanh điều hướng
  • .navigationTitle — đặt tiêu đề màn hình ở chế độ large hoặc inline

NavigationView là gì?

NavigationView là một vùng chứa SwiftUI bao bọc một hệ thống phân cấp các màn hình và cung cấp giao diện điều hướng. Bên trong NavigationView hoạt động NavigationLink — một phần tử khi nhấn vào sẽ thay thế màn hình hiện tại bằng màn hình mới. NavigationView tự động thêm thanh điều hướng với tiêu đề và nút «Quay lại».

NavigationView xuất hiện trong iOS 13 cùng với SwiftUI. Về mặt khái niệm, nó thay thế UINavigationController từ UIKit nhưng được triển khai theo hướng khai báo. Thay vì push/pop thủ công, nhà phát triển mô tả mối quan hệ giữa các màn hình thông qua NavigationLink. Hệ thống tự động quản lý ngăn xếp.

NavigationView hỗ trợ các bổ trợ .navigationTitle, .navigationBarTitleDisplayMode, .toolbar và .searchable. Đối với iOS 16+, Apple đã giới thiệu NavigationStack, bảo tồn API của NavigationView nhưng bổ sung quản lý ngăn xếp lập trình thông qua NavigationPath. Đối với các dự án hỗ trợ iOS 15 trở xuống, NavigationView vẫn là lựa chọn duy nhất.

NavigationLink là một phần tử SwiftUI tạo chuyển tiếp đến màn hình đích bên trong NavigationView hoặc NavigationStack. Khi nhấn NavigationLink, hệ thống thêm màn hình đích vào ngăn xếp điều hướng. Hoạt ảnh chuyển tiếp là push tiêu chuẩn từ bên phải trên iOS, thích ứng với nền tảng.

swift
struct ContentView: View {
    var body: some View {
        NavigationView {
            List(items) { item in
                NavigationLink(destination: DetailView(item: item)) {
                    Text(item.title)
                }
            }
            .navigationTitle("Danh sách")
        }
    }
}

struct DetailView: View {
    let item: Item

    var body: some View {
        VStack {
            Text(item.description)
                .navigationTitle(item.title)
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

NavigationLink nhận hai tham số: destination — View đích, và label — phần tử người dùng nhấn vào. Đối với danh sách, cú pháp với value và NavigationLink(value:) rất tiện lợi — nó tự động bỏ chọn ô và hoạt động với NavigationPath.

Với iOS 16, Apple đã giới thiệu NavigationStack như một sự thay thế cho NavigationView. NavigationStack bảo tồn cú pháp khai báo nhưng bổ sung một tính năng cực kỳ quan trọng — quản lý ngăn xếp lập trình thông qua thuộc tính path kiểu NavigationPath hoặc một mảng Hashable.

Tính năngNavigationView (iOS 13-15)NavigationStack (iOS 16+)
Push lập trìnhKhông, chỉ qua NavigationLinkCó, qua path.append(value)
popToRootChỉ dismiss đến rootpath.removeLast(path.count)
Deep LinksTriển khai phức tạpHỗ trợ tích hợp qua path
Kiểu ngăn xếpKhông (bất kỳ View nào trong destination)Có (mảng giá trị Hashable)
SplitView iPadColumnStyle / StackStyleNavigationSplitView (iOS 16+)

Đối với các dự án có phiên bản tối thiểu iOS 16+, hãy sử dụng NavigationStack. Đối với hỗ trợ iOS 14-15 — NavigationView. NavigationStack không có tương tự trực tiếp cho các phiên bản cũ, vì vậy nâng cấp yêu cầu kiểm tra tương thích.

Toolbar và cấu hình navigationTitle

Các bổ trợ .toolbar.navigationTitle kiểm soát nội dung của thanh điều hướng. .navigationTitle đặt tiêu đề màn hình, .navigationBarTitleDisplayMode chọn kiểu: .large (lớn, mặc định) hoặc .inline (gọn nhẹ, như trong Cài đặt). .toolbar thêm nút, tìm kiếm và điều khiển phân đoạn.

swift
struct SettingsView: View {
    var body: some View {
        NavigationStack {
            Form {
                Section("Hồ sơ") {
                    Text("Tên người dùng")
                    Toggle("Thông báo", isOn: $notifications)
                }
            }
            .navigationTitle("Cài đặt")
            .navigationBarTitleDisplayMode(.large)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Lưu") { save() }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    EditButton()
                }
            }
        }
    }
}

.searchable là một bổ trợ khác tích hợp thanh tìm kiếm vào thanh điều hướng. Hoạt động với cả NavigationView và NavigationStack. Tìm kiếm tự động ẩn khi cuộn và hiện ra khi vuốt xuống. Hỗ trợ lọc danh sách thông qua Binding String.

Điều hướng lập trình với NavigationPath

NavigationPath là một kiểu iOS 16+ đại diện cho ngăn xếp điều hướng như một tập hợp các giá trị Hashable. Nhà phát triển thêm các phần tử vào path để chuyển tiếp lập trình và xóa chúng để quay lại. NavigationPath hỗ trợ deep link, thông báo push và khôi phục trạng thái.

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

    var body: some View {
        NavigationStack(path: $path) {
            List(categories) { category in
                NavigationLink("Danh mục \(category.name)",
                               value: category)
            }
            .navigationTitle("Danh mục")
            .navigationDestination(for: Category.self) { category in
                ProductListView(category: category)
            }
            .navigationDestination(for: Product.self) { product in
                ProductDetailView(product: product)
            }
        }

        // Chuyển tiếp lập trình qua deep link
        .onOpenURL { url in
            guard let productId = DeepLinkParser.parse(url) else { return }
            path.append(Product(id: productId))
        }
    }
}

.navigationDestination(for:) đăng ký một kiểu dữ liệu để hiển thị màn hình. Khi một giá trị thuộc kiểu này được thêm vào path, hệ thống tự động tạo View đích. Cách tiếp cận này thay thế NavigationLink(destination:) rõ ràng và làm cho điều hướng được nhập kiểu chặt chẽ.

NavigationView và NavigationStack hoạt động trên tất cả các nền tảng Apple: iOS, iPadOS, watchOS, tvOS và macOS. Hành vi thích ứng với màn hình. Trên iPad, NavigationStack hỗ trợ NavigationSplitView, thay thế UISplitViewController từ UIKit và hiển thị hai cột trên màn hình rộng.

NavigationSplitView (iOS 16+) chia màn hình thành thanh bên (danh sách) và chi tiết. Trên iPhone, thanh bên bị ẩn, chỉ hiển thị chi tiết qua NavigationLink. Trên iPad, thanh bên và chi tiết được hiển thị đồng thời ở chế độ split.

swift
struct AdaptiveNavigation: View {
    @State private var selectedCategory: Category?

    var body: some View {
        NavigationSplitView {
            List(categories, selection: $selectedCategory) { category in
                Text(category.name)
            }
            .navigationTitle("Danh mục")
        } detail: {
            ProductListView(category: selectedCategory)
        }
    }
}

NavigationSplitView tự động chọn chế độ hiển thị tối ưu cho mỗi thiết bị. Trên iPhone ở chế độ dọc — ngăn xếp, trên iPad và iPhone ở chế độ ngang — split. Nhà phát triển không cần viết mã riêng cho các lớp kích thước khác nhau.

Câu hỏi thường gặp

Sự khác biệt giữa NavigationView và NavigationStack là gì?

NavigationView là API cũ (iOS 13-15), chỉ hỗ trợ NavigationLink khai báo. NavigationStack là API mới (iOS 16+), bổ sung path cho điều hướng lập trình, deep link và ngăn xếp được nhập kiểu chặt chẽ. Apple khuyên dùng NavigationStack cho các dự án mới.

Làm thế nào để thêm nút vào thanh điều hướng?

Thông qua bổ trợ .toolbar với ToolbarItem. Ví dụ: .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button('Cài đặt') { } } }. Placement xác định vị trí: trailing (phải), leading (trái), principal (giữa).

Làm thế nào để cấu hình tiêu đề và kiểu của nó?

Tiêu đề được đặt qua .navigationTitle('Tiêu đề'). Kiểu — .navigationBarTitleDisplayMode(.large) hoặc .inline. Large — tiêu đề lớn kiểu iOS Music, inline — gọn nhẹ, như trong Cài đặt. Kiểu có thể thay đổi cho từng màn hình riêng lẻ.

Làm thế nào để truyền dữ liệu qua NavigationLink?

Ba cách: qua value (NavigationLink(value:item) { Label }, iOS 16+), qua destination + label, qua isActive để chuyển tiếp lập trình. NavigationLink với value sạch hơn cho danh sách vì không yêu cầu tạo View đích trước khi chuyển tiếp.

Có thể sử dụng NavigationView trên watchOS và tvOS không?

Có. NavigationView và NavigationStack có sẵn trên iOS, iPadOS, watchOS, tvOS và macOS. Trên watchOS, điều hướng sử dụng hệ thống phân cấp giao diện với Digital Crown, trên tvOS — đầu vào dựa trên tiêu điểm với điều khiển từ xa. Hành vi tự động thích ứng với nền tảng.

Tổng kết

  • NavigationView — vùng chứa SwiftUI cho điều hướng ngăn xếp với thanh điều hướng tự động và nút Quay lại
  • NavigationLink — phần tử chuyển tiếp chính, hỗ trợ cú pháp khai báo (destination) và dựa trên value
  • NavigationStack (iOS 16+) thay thế NavigationView, bổ sung quản lý ngăn xếp lập trình qua NavigationPath
  • .toolbar thêm nút vào thanh điều hướng, .navigationTitle đặt tiêu đề với lựa chọn kiểu large/inline
  • NavigationPath — ngăn xếp được nhập kiểu chặt chẽ của các giá trị Hashable cho điều hướng lập trình và deep link
  • NavigationSplitView (iOS 16+) thích ứng giao diện cho iPad và iPhone, tự động chọn split hoặc ngăn xếp
  • Sự lựa chọn giữa NavigationView và NavigationStack được xác định bởi phiên bản iOS tối thiểu được hỗ trợ trong dự án

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm