SwiftUI: nó là gì, các khái niệm chính và View Protocol

Tác giả: IT Sectr Đã đăng: 2026-04-30 Thời gian đọc: 8 phút

SwiftUI là một framework khai báo của Apple để xây dựng giao diện người dùng trên tất cả các nền tảng của hệ sinh thái. Thay vì mô tả các bước một cách mệnh lệnh, nhà phát triển khai báo giao diện sẽ trông như thế nào và SwiftUI quản lý việc hiển thị và cập nhật của nó. Theo Apple Developer Documentation (2025), SwiftUI hỗ trợ iOS 15+, iPadOS 15+, macOS 12+, watchOS 8+ và tvOS 15+ và sử dụng View Protocol làm khối xây dựng cơ bản cho tất cả các thành phần giao diện.

Những điểm chính

  • SwiftUI là một framework khai báo của Apple, nơi nhà phát triển mô tả giao diện và các bản cập nhật được thực hiện tự động.
  • View Protocol với thuộc tính body là nền tảng của mọi thành phần UI SwiftUI, trả về mô tả màn hình thông qua thành phần của các view.
  • Property Wrappers — @State, @Binding, @ObservedObject, @StateObject — quản lý trạng thái và kích hoạt việc vẽ lại khi dữ liệu thay đổi.
  • NavigationStack (iOS 16+) là API điều hướng hiện đại với các route an toàn kiểu và chuyển tiếp khai báo.
  • Modifier là một chuỗi các lời gọi để tùy chỉnh giao diện và hành vi của view mà không cần kế thừa lớp.

SwiftUI là gì?

SwiftUI là một framework khai báo được Apple giới thiệu vào năm 2019 để thay thế UIKit trong các dự án mới. Thay vì tạo thủ công các phiên bản UIView và thêm chúng vào hệ thống phân cấp, nhà phát triển mô tả giao diện thông qua các cấu trúc tuân thủ giao thức View. SwiftUI tự động tính toán sự khác biệt giữa trạng thái hiện tại và trạng thái mới và chỉ vẽ lại các phần đã thay đổi bằng công cụ hiển thị của riêng nó.

Framework được viết bằng Swift sử dụng ngữ nghĩa giá trị (cấu trúc, không phải lớp), làm cho các thành phần UI nhẹ và an toàn luồng. Không giống như UIKit, nơi UIViewController có thể nặng 200+ byte do runtime Objective-C, SwiftUI View chỉ đơn giản là một cấu trúc có kích thước vài byte. Điều này đặc biệt quan trọng đối với watchOS với bộ nhớ hạn chế.

Đa nền tảng SwiftUI

Cùng một mô tả View hoạt động trên iPhone, iPad, Mac, Apple Watch, Apple TV và Apple Vision Pro. SwiftUI điều chỉnh giao diện theo nền tảng: cử chỉ chạm trên iOS, tổ hợp phím trên macOS, cuộn Digital Crown trên watchOS. Điều này giảm thời gian phát triển cho các công ty phát hành ứng dụng trên nhiều nền tảng Apple nhưng yêu cầu cấu hình bổ sung cho các yếu tố cụ thể của từng nền tảng.

View Protocol và phần thân của view

Trong SwiftUI, mỗi màn hình là một cấu trúc thực hiện giao thức View với một yêu cầu duy nhất: một thuộc tính được tính toán body kiểu some View. Từ khóa some (kiểu không rõ ràng) ẩn kiểu cụ thể của view, cho phép SwiftUI tối ưu hóa việc hiển thị. Bên trong body, nhà phát triển kết hợp các thành phần có sẵn — Text, Image, Button, List — bằng ViewBuilder, nó tập hợp nhiều view thành một.

swift
struct GreetingView: View {
    let name: String

    var var body: some View {
        VStack {
            Text("Xin chào, \(name)!")
                .font(.title)
                .foregroundColor(.blue)
            Image(systemName: "hand.wave")
                .imageScale(.large)
        }
        .padding()
    }
}

Trong ví dụ, VStack (ngăn xếp dọc) chứa Text và Image. Giá trị của name được truyền qua trình khởi tạo cấu trúc — đây là cách DI (Dependency Injection) hoạt động trong SwiftUI mà không cần vùng chứa DI bên ngoài. Mỗi bổ ngữ trả về một view mới với thay đổi đã được áp dụng mà không làm thay đổi bản gốc. Điều này có được nhờ tính bất biến của các kiểu giá trị.

ViewBuilder và điều kiện

ViewBuilder là một trình xây dựng kết quả được chú thích bằng @resultBuilder, tập hợp tối đa 10 view thành một. Bên trong body, có thể sử dụng if/else, switch và ForEach mà không cần trình bọc bổ sung. ForEach hoạt động với các phần tử Identifiable — mỗi view được gán một id duy nhất để tạo hiệu ứng hoạt ảnh chính xác khi chèn/xóa.

Quản lý trạng thái: @State, @Binding, @ObservedObject

Trong SwiftUI, trạng thái xác định nội dung được hiển thị trên màn hình. Khi trạng thái thay đổi, SwiftUI tạo lại body của view phụ thuộc và so sánh kết quả với kết quả trước đó bằng thuật toán diff. Để lưu trữ trạng thái, các trình bọc thuộc tính được sử dụng — mỗi cái giải quyết nhiệm vụ cụ thể của nó: trạng thái cục bộ, kết nối với view con hoặc mô hình dữ liệu bên ngoài.

swift
struct CounterView: View {
    @State private var count = 0

    var var body: some View {
        VStack {
            Text("Bộ đếm: \(count)")
            Button("Tăng") {
                count += 1
            }
        }
    }
}

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = 0
}

@State lưu trữ một giá trị đơn giản cục bộ (Int, String, Bool) bên trong cấu trúc View. SwiftUI di chuyển bộ nhớ từ cấu trúc sang bộ lưu trữ riêng — do đó, thuộc tính với @State có thể thay đổi ngay cả khi View là kiểu giá trị. @ObservableObject dành cho các lớp có thuộc tính @Published, những thay đổi của chúng tự động thông báo cho SwiftUI về nhu cầu vẽ lại.

@Binding và kết nối cha-con

@Binding tạo kết nối hai chiều với nguồn dữ liệu nằm trong view cha. Cha truyền $variable (giá trị được chiếu) và con đọc và ghi giá trị thông qua binding. Điều này cho phép di chuyển đầu vào văn bản hoặc công tắc sang một thành phần riêng biệt trong khi vẫn giữ trạng thái ở cha. Nếu không có @Binding, mỗi thay đổi sẽ yêu cầu một bao đóng callback để truyền giá trị mới lên trên.

Trước iOS 16, điều hướng trong SwiftUI được xây dựng trên NavigationView — một API cũ với hành vi phức tạp trên iPad (chế độ xem chia đôi, hai cột). Bắt đầu từ iOS 16, Apple khuyến nghị NavigationStack — một giải pháp thay thế đơn giản hóa với các route an toàn kiểu. Nhà phát triển định nghĩa một enum các route có thể và NavigationStack tự động quản lý ngăn xếp màn hình với hỗ trợ deep link và quay lại gốc.

swift
enum Route: Hashable {
    case detail(id: Int)
    case settings
}

struct ContentView: View {
    var var body: some View {
        NavigationStack {
            List {
                NavigationLink("Màn hình chi tiết",
                               value: Route.detail(id: 42))
                NavigationLink("Cài đặt",
                               value: Route.settings)
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .detail(let id): DetailView(id: id)
                case .settings: SettingsView()
                }
            }
        }
    }
}

Các route tuân thủ Hashable cho phép sử dụng bất kỳ kiểu dữ liệu nào để truyền tham số. navigationDestination(for:destination:) liên kết kiểu route với view đích. Lợi thế so với điều hướng UIKit là không cần vẽ lại khi thêm route mới: chỉ cần thêm một case vào enum và một trình xử lý trong switch. Deep link được xử lý thông qua processDeepLink trên NavigationStack.

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

Để điều hướng lập trình (sau khi đăng nhập, hẹn giờ hoặc phản hồi máy chủ), @State được sử dụng với trình khởi tạo NavigationLink: NavigationLink(isActive: $isActive). Khi isActive = true, quá trình chuyển đổi diễn ra mà không cần chạm của người dùng. Một giải pháp thay thế là binding mảng $path trong NavigationStack: $path.append(Route.detail(id: 1)).

View Modifier — tùy chỉnh giao diện

Modifier là một phương thức trả về một bản sao đã được sửa đổi của view. Không giống như UIKit, nơi cấu hình thuộc tính được thực hiện bằng cách thay đổi một view hiện có, SwiftUI tạo ra một giá trị mới với thay đổi đã được áp dụng. Chuỗi bổ ngữ xây dựng giao diện cuối cùng từ các biến đổi tuần tự: phông chữ → đệm → màu sắc → bóng → cử chỉ.

Apple cung cấp hơn 200 bổ ngữ tích hợp. Phổ biến nhất: .font(), .foregroundColor(), .padding(), .background(), .cornerRadius(), .shadow(), .opacity(), .offset(). Thứ tự của các bổ ngữ rất quan trọng: .padding() trước .background() tô màu vùng có đệm, sau đó — chỉ vùng bên trong. Các bổ ngữ tùy chỉnh được tạo thông qua giao thức ViewModifier.

Bổ ngữ có điều kiện và hoạt ảnh

Các bổ ngữ có thể được áp dụng có điều kiện thông qua toán tử ba ngôi: .foregroundColor(isError ? .red : .primary). Đối với hoạt ảnh, .animation(.easeInOut, value: state) được sử dụng — bổ ngữ hoạt ảnh được gắn với một thuộc tính trạng thái cụ thể. Khi thuộc tính này thay đổi, SwiftUI tạo hoạt ảnh chuyển tiếp giữa giá trị cũ và giá trị mới. Hoạt ảnh hoạt động với opacity, offset, scale, rotation, kích thước và màu sắc — mỗi thuộc tính có một AnimatableParameter tương ứng.

Đối với hoạt ảnh tùy chỉnh, có sẵn .transition (xuất hiện/biến mất) và .matchedGeometryEffect (chuyển tiếp mượt mà của một phần tử giữa hai vùng chứa). Cái sau được sử dụng cho hoạt ảnh hero trong danh sách: một biểu tượng trong ô danh sách biến đổi mượt mà thành hình ảnh lớn trên màn hình chi tiết.

SwiftUI vs UIKit: so sánh các phương pháp

Việc lựa chọn giữa SwiftUI và UIKit là một trong những tình huống khó xử đầu tiên của nhà phát triển iOS. Cả hai framework đều được Apple hỗ trợ nhưng giải quyết vấn đề xây dựng giao diện theo những cách hoàn toàn khác nhau: SwiftUI khai báo, UIKit mệnh lệnh. Sự khác biệt thể hiện ở quản lý trạng thái, điều hướng, hiệu suất và khả năng tương thích.

Khía cạnhSwiftUIUIKit
Phương phápKhai báo: hiển thị gìMệnh lệnh: cách xây dựng
Trạng tháiProperty Wrappers, tự động vẽ lạiThủ công: reloadData, setNeedsLayout
Mã UINhỏ gọn, chuỗi bổ ngữDài dòng, NSCoder/Storyboard/ràng buộc
Hiệu suấtCao trên iOS 17+, thuật toán diffCao nhất trên iOS 12–16, kiểm soát trực tiếp
Phiên bản tối thiểuiOS 15+ (hỗ trợ đầy đủ)iOS 2+ (tất cả phiên bản)

Đối với các dự án mới với phiên bản tối thiểu iOS 17, Apple khuyến nghị SwiftUI làm framework chính. UIKit vẫn cần thiết cho các giao diện yêu cầu kiểm soát tinh vi đối với việc hiển thị (UICollectionViewLayout tùy chỉnh, cảnh CAAnimation phức tạp) hoặc hỗ trợ iOS 12–14. Nhiều dự án sử dụng phương pháp kết hợp: SwiftUI thông qua UIHostingController được nhúng vào ứng dụng UIKit và UIViewRepresentable cho phép sử dụng các thành phần UIKit trong hệ thống phân cấp SwiftUI.

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

Có thể sử dụng SwiftUI và UIKit trong cùng một dự án không?

Có, thông qua UIHostingController (SwiftUI trong UIKit) và UIViewRepresentable (UIKit trong SwiftUI). Đây là phương pháp kết hợp, phổ biến trong quá trình di chuyển.

Nên bắt đầu dự án SwiftUI từ phiên bản iOS nào?

iOS 17 cung cấp đầy đủ chức năng: NavigationStack, Observation framework, Swift Charts. iOS 15 là ngưỡng tối thiểu cho sản xuất.

Tại sao SwiftUI đôi khi không cập nhật giao diện?

Nguyên nhân phổ biến nhất là thay đổi thuộc tính @Published trên luồng nền. ObservableObject phải gửi các thay đổi trên main actor: @MainActor class ViewModel.

Làm thế nào để xử lý debounce khi nhấn nút trong SwiftUI?

Sử dụng .debounce thông qua Combine: Button.publisher(for: .tap) .debounce(for: .seconds(0.3), scheduler: RunLoop.main).

SwiftUI có hỗ trợ cử chỉ tùy chỉnh không?

Có, thông qua các bổ ngữ Gesture: DragGesture, LongPressGesture, MagnificationGesture, RotationGesture. Kết hợp chúng bằng .simultaneousGesture() và .sequenced().

Tóm tắt

  • SwiftUI là framework khai báo của Apple, nơi giao diện được mô tả như một tổ hợp các cấu trúc View với các trình bọc thuộc tính để quản lý trạng thái.
  • View Protocol với thuộc tính được tính toán body là điểm vào duy nhất cho mọi view. ViewBuilder tập hợp tối đa 10 view thành một mà không cần vùng chứa bổ sung.
  • @State, @Binding@ObservedObject bao phủ tất cả các tình huống quản lý dữ liệu: trạng thái cục bộ, kết nối cha-con và mô hình bên ngoài.
  • NavigationStack với các route enum an toàn kiểu đã thay thế NavigationView, thêm hỗ trợ cho deep link và điều hướng lập trình.
  • Modifier là một mẫu chính của SwiftUI cho phép tùy chỉnh giao diện của view thông qua chuỗi lời gọi mà không cần kế thừa.
  • SwiftUI và UIKit cùng tồn tại thông qua UIHostingController và UIViewRepresentable, cho phép di chuyển dự án dần dần.
  • Đối với iOS 17+, Apple khuyến nghị SwiftUI làm framework chính; UIKit vẫn dành cho các giao diện tùy chỉnh phức tạp và hỗ trợ các phiên bản cũ.

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