Những đặc điểm của Enum trong Swift
Bài đăng này đã không được cập nhật trong 6 năm
Enum là gì?
An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.
=> Enum định nghĩa 1 nhóm các giá trị có liên quan đến nhau và cho phép bạn làm việc với những giá trị đó 1 cách an toàn trong code của bạn
Nhắc lại 1 chút về định nghĩa cho vui thôi bài viết này mình sẽ tập trung nói về cú pháp, cách sử dụng và cùng sử dụng nó trong các bài toán thực tế.
Enum cơ bản
Nếu bạn làm việc với scroll direction, bài toán đặt ra là bạn cần phải xác định được chiều scroll. Chắc hẳn khi các bạn tập tọe code thì điều đầu tiên các bạn nghĩ đến là là tạo 1 biến thế này đúng không? (trước mình toàn thế thôi á )
var isScrollUp = true
Nhưng thế này là không ổn nhé. Vì không may scrollView của bạn scroll được cả 4 hướng thì sao? (khóc-ing)
Trong tình huống đó thì enum sẽ là sự lựa chọn hoàn hảo, cùng xem ví dụ nhé:
enum ScrollDirection {
case left
case right
case up
case down
}
Và sau đó bạn hoàn toàn có thể control việc scroll nhé: (cười)
let scrollDirection = ScrollDirection.down
switch scrollDirection {
case .down:
print("scroll down")
default:
break
}
if case .down == scrollDirection {
print("scroll down")
}
if scrollDirection == .down {
print("scroll down")
}
Enum values
Trong nhiều trường hợp bạn cần set giá trị cho từng case của enum để tiện sử dụng. Hiểu được điều này Swift cung cấp nhiều cách để bạn có thể set giá trị cho nó
// Mapping to Integer
enum Movement: Int {
case left = 0
case right = 1
case top = 2
case bottom = 3
}
// You can also map to strings
enum House: String {
case baratheon = "Ours is the Fury"
case greyjoy = "We Do Not Sow"
case martell = "Unbowed, Unbent, Unbroken"
case stark = "Winter is Coming"
case tully = "Family, Duty, Honor"
case tyrell = "Growing Strong"
}
// Or to floating point (also note the fancy unicode in enum cases)
enum Constants: Double {
case π = 3.14159
case e = 2.71828
case φ = 1.61803398874
case λ = 1.30357
}
Trong trường hợp giá trị của case trong Enum là Int hoặc String. Bạn có thể bỏ qua giá trị của nó mà Swift vẫn tự hiểu và chạy đúng:
// Mercury = 1, Venus = 2, ... Neptune = 8
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
// North = "North", ... West = "West"
enum CompassPoint: String {
case North, South, East, West
}
Nesting Enums
Hãy tưởng tượng một nhân vật trong một trò chơi. Mỗi nhân vật có thể có một vũ khí, tất cả các nhân vật đều có quyền truy cập cùng một bộ vũ khí. Tất cả các nhân vật khác trong trò chơi không có quyền truy cập vào những vũ khí (họ đang có nhiệm vụ khác...)
enum Character {
enum Weapon {
case Bow
case Sword
case Lance
case Dagger
}
enum Helmet {
case Wooden
case Iron
case Diamond
}
case Thief
case Warrior
case Knight
}
Bây giờ bạn có một hệ thống có thứ bậc để mô tả các mục khác nhau mà nhân vật của bạn có quyền truy cập rồi:
let character = Character.Thief
let weapon = Character.Weapon.Bow
let helmet = Character.Helmet.Iron
Containing Enums
Để dễ hiểu: Containing Enums có nghĩa là bạn có thể để enum nằm trong struct hay class khác. Vẫn với ví dụ về vũ khí bên trên nhé:
struct Character {
enum CharacterType {
case Thief
case Warrior
case Knight
}
enum Weapon {
case Bow
case Sword
case Lance
case Dagger
}
let type: CharacterType
let weapon: Weapon
}
let warrior = Character(type: .Warrior, weapon: .Sword)
Nó vẫn giúp giữ thông tin liên hệ gữa các đối tuơng đúng không?
Associated values
Đây là 1 cách tuyệt vời để bạn có thể gắn thêm thông tin vào 1 enum case. Ví dụ bạn cần xây định nghĩa barcode của sản phẩm. Có 2 loaị barcode là UPC gồm 4 chữ số, và QRCode là 1 đoạn String. Bạn có thể định nghĩa nó như sau:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
Khi đó bạn có thể tạo 1 biến barcode như sau:
var productBarcodeUPC = Barcode.upc(8, 85909, 51226, 3)
var productBarcodeQr = Barcode.qrCode("ABCDEFGHIJKLMNOP")
Để so sánh 1 enum có Associated values bạn có thể làm như sau:
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
print("QR code: \(productCode).")
}
bạn có thể bỏ "let" (hoặc var) đi và dùng như sau:
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
Methods
Bạn có thể thêm các hàm cho enum như sau:
enum Device: String {
case iphone
case ipad
case tv
case watch
func getOS() -> String {
switch self {
case .ipad, .iphone:
return "iOS"
case .watch:
return "WatchOS"
case .tv:
return "tvOS"
}
}
}
Properties
Bạn không thể thêm Stored Properties cho enum. Nhưng bạn vẫn có thể tạo computed properties như sau:
enum Device: String {
case iphone
case ipad
case tv
case watch
var description: String {
switch self {
case .ipad, .iphone:
return "iOS"
case .watch:
return "WatchOS"
case .tv:
return "tvOS"
}
}
}
Static Methods
Bạn cũng có thể thêm 1 static methods cho enum như sau:
enum Device: String {
case iphone
case ipad
case tv
case watch
static func biggestDevice() -> Device {
return Device.tv
}
}
print(Device.biggestDevice())
Mutating Methods
Các methods có thể viết dưới dang mutating, và cho phép bạn thay đổi case của chính self:
enum DeviceMode {
case metting
case outdoor
case silent
case normal
mutating func setSilent() {
self = .silent
}
}
var deviceMode = DeviceMode.metting
deviceMode.setSilent()
print(deviceMode)
Advanced Enum Usage
Protocols
Swift cho phép bạn sử dụng Protocols và Protocol Extensions với Enum:
protocol CustomStringConvertible {
var description: String { get }
}
enum DeviceMode: String, CustomStringConvertible {
case metting
case outdoor
case silent
case normal
var description: String {
return self.rawValue
}
}
Extensions
Bạn có thể sử dụng extension để bổ sung các properties và methods:
enum DeviceMode: String {
case metting
case outdoor
case silent
case normal
}
extension DeviceMode {
var volume: Int {
switch self {
case .metting:
return 10
case .outdoor:
return 100
case .silent:
return 0
case .normal:
return 50
}
}
}
Use Enum for Error Handling
Bạn có thể sử dụng Enum để định nghĩa tập hợp các lỗi có thể gặp phải. Khi định nghĩa lỗi Decode Data:
enum DecodeError: Error {
case typeMismatch(expected: String, actual: String)
case missingKey(String)
case custom(String)
}
Khi định nghĩa lỗi API:
enum APIError : Error {
// Can't connect to the server (maybe offline?)
case connectionError(error: NSError)
// The server responded with a non 200 status code
case serverError(statusCode: Int, error: NSError)
// We got no data (0 bytes) back from the server
case noDataError
// The server response can't be converted from JSON to a Dictionary
case jsonSerializationError(error: Error)
// The Argo decoding Failed
case jsonMappingError(converstionError: DecodeError)
}
Dùng để định nghĩa HTTP status error:
enum HttpError: String {
case Code400 = "Bad Request"
case Code401 = "Unauthorized"
case Code402 = "Payment Required"
case Code403 = "Forbidden"
case Code404 = "Not Found"
}
Trên đây là những gì tìm hiểu và sưu tầm được, nếu có gì sai sót mong các bạn bổ sung giúp mình
Nguồn:
All rights reserved