枚举 #

一、枚举概述 #

枚举为一组相关值定义一个通用类型,使代码更安全、更易读。

1.1 枚举特点 #

  • 值类型
  • 支持关联值
  • 支持原始值
  • 支持方法和属性

二、基本枚举 #

2.1 定义枚举 #

swift
enum Direction {
    case north
    case south
    case east
    case west
}

enum CompassPoint {
    case north, south, east, west
}

let direction = Direction.north
print(direction)

2.2 使用枚举 #

swift
var currentDirection = Direction.north
currentDirection = .south

switch currentDirection {
case .north:
    print("向北")
case .south:
    print("向南")
case .east:
    print("向东")
case .west:
    print("向西")
}

三、关联值 #

3.1 基本用法 #

swift
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem)-\(manufacturer)-\(product)-\(check)")
case .qrCode(let productCode):
    print("QR: \(productCode)")
}

3.2 提取关联值 #

swift
enum Response {
    case success(Data)
    case failure(Error)
}

func handle(response: Response) {
    switch response {
    case .success(let data):
        print("成功: \(data)")
    case .failure(let error):
        print("失败: \(error)")
    }
}

3.3 实际应用 #

swift
enum NetworkResponse {
    case loading
    case success(User)
    case error(String)
}

func handle(response: NetworkResponse) {
    switch response {
    case .loading:
        print("加载中...")
    case .success(let user):
        print("用户: \(user.name)")
    case .error(let message):
        print("错误: \(message)")
    }
}

四、原始值 #

4.1 基本用法 #

swift
enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

print(ASCIIControlCharacter.tab.rawValue)

4.2 隐式原始值 #

swift
enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

print(Planet.earth.rawValue)

if let planet = Planet(rawValue: 3) {
    print(planet)
}

4.3 字符串原始值 #

swift
enum Direction: String {
    case north = "北"
    case south = "南"
    case east = "东"
    case west = "西"
}

print(Direction.north.rawValue)

if let direction = Direction(rawValue: "南") {
    print(direction)
}

五、递归枚举 #

5.1 indirect关键字 #

swift
enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

indirect enum Expr {
    case number(Int)
    case add(Expr, Expr)
    case multiply(Expr, Expr)
}

func evaluate(_ expression: Expr) -> Int {
    switch expression {
    case .number(let value):
        return value
    case .add(let left, let right):
        return evaluate(left) + evaluate(right)
    case .multiply(let left, let right):
        return evaluate(left) * evaluate(right)
    }
}

let expr = Expr.multiply(
    Expr.add(Expr.number(2), Expr.number(3)),
    Expr.number(4)
)
print(evaluate(expr))

六、枚举方法和属性 #

6.1 方法 #

swift
enum Direction {
    case north, south, east, west
    
    func opposite() -> Direction {
        switch self {
        case .north: return .south
        case .south: return .north
        case .east: return .west
        case .west: return .east
        }
    }
    
    mutating func turnRight() {
        switch self {
        case .north: self = .east
        case .south: self = .west
        case .east: self = .south
        case .west: self = .north
        }
    }
}

var direction = Direction.north
print(direction.opposite())
direction.turnRight()
print(direction)

6.2 计算属性 #

swift
enum Season {
    case spring, summer, autumn, winter
    
    var months: [String] {
        switch self {
        case .spring: return ["3月", "4月", "5月"]
        case .summer: return ["6月", "7月", "8月"]
        case .autumn: return ["9月", "10月", "11月"]
        case .winter: return ["12月", "1月", "2月"]
        }
    }
    
    var temperature: String {
        switch self {
        case .spring: return "温暖"
        case .summer: return "炎热"
        case .autumn: return "凉爽"
        case .winter: return "寒冷"
        }
    }
}

print(Season.summer.months)
print(Season.winter.temperature)

七、协议遵循 #

7.1 遵循协议 #

swift
enum Direction: CaseIterable {
    case north, south, east, west
}

print(Direction.allCases.count)

for direction in Direction.allCases {
    print(direction)
}

7.2 Codable #

swift
enum Status: String, Codable {
    case pending = "pending"
    case approved = "approved"
    case rejected = "rejected"
}

struct Task: Codable {
    let id: Int
    let status: Status
}

let json = """
{"id": 1, "status": "approved"}
"""

let task = try JSONDecoder().decode(Task.self, from: json.data(using: .utf8)!)
print(task.status)

八、实际应用 #

8.1 状态机 #

swift
enum LoadingState {
    case idle
    case loading
    case loaded(Data)
    case error(Error)
    
    var isLoading: Bool {
        if case .loading = self { return true }
        return false
    }
    
    var data: Data? {
        if case .loaded(let data) = self { return data }
        return nil
    }
}

class ViewModel {
    var state: LoadingState = .idle
    
    func load() {
        state = .loading
        
        DispatchQueue.global().async {
            Thread.sleep(forTimeInterval: 1)
            
            DispatchQueue.main.async {
                self.state = .loaded(Data())
            }
        }
    }
}

8.2 结果类型 #

swift
enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
    
    func map<T>(_ transform: (Success) -> T) -> Result<T, Failure> {
        switch self {
        case .success(let value):
            return .success(transform(value))
        case .failure(let error):
            return .failure(error)
        }
    }
    
    func get() throws -> Success {
        switch self {
        case .success(let value):
            return value
        case .failure(let error):
            throw error
        }
    }
}

8.3 配置类型 #

swift
enum Environment {
    case development
    case staging
    case production
    
    var baseURL: String {
        switch self {
        case .development:
            return "http://localhost:3000"
        case .staging:
            return "https://staging.api.example.com"
        case .production:
            return "https://api.example.com"
        }
    }
    
    var apiKey: String {
        switch self {
        case .development:
            return "dev_key"
        case .staging:
            return "staging_key"
        case .production:
            return "prod_key"
        }
    }
}

九、总结 #

本章学习了Swift枚举:

  • 基本枚举:定义和使用
  • 关联值:存储额外信息
  • 原始值:预定义值
  • 递归枚举:嵌套结构

最佳实践:

  • 使用枚举表示有限状态
  • 使用关联值携带数据
  • 遵循协议增加功能
  • 配合switch使用

下一章,我们将学习结构体!

最后更新:2026-03-26