Enum trong Swift là một kiểu hợp nhất một nhóm các giá trị liên quan dưới một tên duy nhất. Khác với C và Objective-C, nơi enum chỉ là một tập hợp các hằng số nguyên, Swift cung cấp enumeration hạng nhất với associated values, raw values, phương thức và hỗ trợ giao thức. Theo Apple, 2026, enum là một trong những công cụ chính để mô hình hóa trạng thái an toàn kiểu trong phát triển iOS.
Các điểm chính
Enum (enumeration) là một kiểu dữ liệu tùy chỉnh hợp nhất một tập hợp hữu hạn các biến thể loại trừ lẫn nhau. Trong Swift, enum không chỉ là các hằng số số, mà là một kiểu hoàn chỉnh với logic riêng.
Mỗi biến thể của enumeration được gọi là một case. Khác với Objective-C, nơi enum chỉ là kiểu số nguyên, Swift cho phép mỗi case lưu trữ dữ liệu riêng và có phương thức.
Theo Apple, enum trong Swift hỗ trợ generic, bộ khởi tạo, thuộc tính tính toán và tuân thủ giao thức — giúp nó có thể áp dụng để mô hình hóa trạng thái, lỗi, tùy chọn và máy trạng thái hữu hạn.
Sử dụng enum bất cứ nơi nào bạn cần biểu diễn một tập hợp hữu hạn các biến thể loại trừ lẫn nhau: trạng thái màn hình, loại lỗi, hướng, tùy chọn lọc.
Enum được khai báo bằng từ khóa enum theo sau là tên và phần thân trong dấu ngoặc nhọn.
enum CompassDirection {
case north
case south
case east
case west
}
Case có thể được khai báo trên một dòng duy nhất, cách nhau bằng dấu phẩy:
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
Để truy cập một case, sử dụng cú pháp dấu chấm sau kiểu đã biết:
let direction = CompassDirection.north
// Đã biết kiểu — cú pháp rút gọn có sẵn:
var currentPlanet = .earth
Khi một biến được gán kiểu enum đã biết, Swift tự động suy luận kiểu, cho phép bỏ qua tên enumeration khi truy cập các case.
Raw Values là các giá trị của một kiểu duy nhất được gán cho mỗi case enum. Khác với associated values, raw values có cùng kiểu cho tất cả các case và được xác định tại thời điểm khai báo.
enum HTTPStatusCode: Int {
case ok = 200
case notFound = 404
case internalServerError = 500
}
let code = HTTPStatusCode.notFound
print(code.rawValue) // 404
Đối với raw values là số nguyên, Swift tự động tăng giá trị nếu chỉ có giá trị đầu tiên được đặt rõ ràng:
enum Status: Int {
case pending = 1
case active // 2
case completed // 3
}
Raw values có thể thuộc các kiểu Int, String, Character hoặc bất kỳ kiểu nào tuân thủ giao thức RawRepresentable. Swift tự động tạo bộ khởi tạo init? để tạo enum từ raw value — thuận tiện cho việc phân tích dữ liệu từ API.
Associated Values cho phép gắn các kiểu dữ liệu khác nhau vào từng case enum riêng lẻ. Khác với raw values, associated values có thể khác nhau về kiểu và số lượng.
enum NetworkError {
case timeout(seconds: Int)
case httpError(code: Int, message: String)
case noConnection
case unknown(error: Error)
}
Khi xử lý với switch, associated values được trích xuất thông qua việc gán vào biến hoặc hằng số:
let error = NetworkError.httpError(code: 403, message: "Forbidden")
switch error {
case .timeout(let seconds):
print("Hết thời gian chờ sau \(seconds)s")
case .httpError(let code, let message):
print("HTTP \(code): \(message)")
case .noConnection:
print("Không có kết nối")
case .unknown(let err):
print("Không xác định: \(err.localizedDescription)")
}
Theo tài liệu Apple, associated values biến enum thành một công cụ biểu cảm để mô hình hóa các trạng thái phức tạp mà không cần tạo các kiểu wrapper riêng biệt. Sử dụng chúng cho các kịch bản giống Result và mô hình hóa lỗi có ngữ cảnh.
Enum đệ quy — một enumeration mà các case của nó tham chiếu đến chính kiểu enum. Các case như vậy được đánh dấu bằng từ khóa indirect.
indirect enum LinkedList<T> {
case empty
case node(value: T, next: LinkedList<T>)
}
Sử dụng indirect trước enum đánh dấu tất cả các case là đệ quy. Ngoài ra, bạn có thể chỉ đánh dấu một case cụ thể bằng indirect:
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
Swift sử dụng indirect để lưu trữ các case đệ quy dưới dạng tham chiếu (ngữ nghĩa tham chiếu) thay vì giá trị — điều này ngăn kích thước enum vô hạn trên stack. Enum đệ quy được sử dụng rộng rãi trong việc xây dựng cây, danh sách liên kết và AST.
Enum có thể tuân thủ giao thức giống như cấu trúc và lớp. Đây là một tính năng chính của lập trình hướng giao thức trong Swift.
protocol Describable {
var description: String { get }
}
enum PaymentMethod: Describable {
case creditCard(last4: String)
case applePay
case bankTransfer
var description: String {
switch self {
case .creditCard(let last4):
return "Card ending in \(last4)"
case .applePay:
return "Apple Pay"
case .bankTransfer:
return "Bank Transfer"
}
}
}
Enum cũng có thể tuân thủ giao thức Cocoa — ví dụ, CaseIterable để tự động tạo tập hợp tất cả các case, hoặc Codable để tuần tự hóa. Điều này làm cho enum trở thành một khối xây dựng linh hoạt trong các ứng dụng Swift.
Câu hỏi thường gặp
Enum là một kiểu với tập hợp hữu hạn các biến thể loại trừ lẫn nhau, trong khi struct là kiểu với tập hợp thuộc tính tùy ý. Enum không thể có stored properties nhưng hỗ trợ computed properties và phương thức.
Không, một enum không thể có cả raw values và associated values cùng lúc. Raw values là giá trị cùng kiểu cho tất cả case, còn associated values là dữ liệu riêng cho từng case. Hai cơ chế này loại trừ lẫn nhau.
Thêm tuân thủ giao thức CaseIterable. Swift sẽ tự động tạo thuộc tính allCases, trả về một tập hợp tất cả các case theo thứ tự khai báo. Điều này thuận tiện cho việc lặp qua tất cả các biến thể.
Switch là cách an toàn nhất vì trình biên dịch kiểm tra tính đầy đủ. Bạn có thể sử dụng if case để kiểm tra một case hoặc == cho enum không có associated values.
Có, enum hỗ trợ generic: enum Result<T, E> { case success(T); case failure(E) }. Điều này cho phép tạo các cấu trúc generic an toàn kiểu để xử lý thành công và lỗi.
Tổng kết
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.
Đọc thêm