Swift-Enum

Swift 枚举是一个非常强大的特性,比许多其他语言的枚举更灵活。以下是 Swift 枚举的完整详解:

1. 基础枚举

基本定义

swift

复制代码
enum CompassPoint {
    case north
    case south
    case east
    case west
}

// 简写方式
enum CompassPoint {
    case north, south, east, west
}

使用

swift

复制代码
var direction = CompassPoint.north
direction = .south  // 类型推断,可以省略枚举名

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

2. 关联值 (Associated Values)

定义关联值

swift

复制代码
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

enum NetworkResponse {
    case success(data: Data, statusCode: Int)
    case failure(error: String, code: Int)
    case loading(progress: Double)
}

使用关联值

swift

复制代码
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 code):
    print("QR code: \(code)")
}

// 如果所有关联值都提取为变量/常量,可以在 case 前声明
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case let .qrCode(code):
    print("QR code: \(code)")
}

3. 原始值 (Raw Values)

定义原始值

swift

复制代码
enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

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

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

使用原始值

swift

复制代码
let earthsOrder = Planet.earth.rawValue  // 3
let sunsetDirection = CompassPoint.west.rawValue  // "west"

// 通过原始值初始化
let possiblePlanet = Planet(rawValue: 7)  // .uranus
let invalidPlanet = Planet(rawValue: 15)  // nil

4. 递归枚举

swift

复制代码
enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

// 或者在整个枚举前加 indirect
indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

递归枚举使用

swift

复制代码
func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

print(evaluate(product))  // (5 + 4) * 2 = 18

5. 方法和属性

实例方法

swift

复制代码
enum TrafficLight {
    case red, yellow, green
    
    func description() -> String {
        switch self {
        case .red: return "停止"
        case .yellow: return "准备"
        case .green: return "通行"
        }
    }
    
    // 修改 self 的变异方法
    mutating func next() {
        switch self {
        case .red: self = .green
        case .yellow: self = .red
        case .green: self = .yellow
        }
    }
}

var light = TrafficLight.red
print(light.description())  // "停止"
light.next()
print(light.description())  // "通行"

计算属性

swift

复制代码
enum Shape {
    case circle(radius: Double)
    case rectangle(width: Double, height: Double)
    
    var area: Double {
        switch self {
        case .circle(let radius):
            return Double.pi * radius * radius
        case .rectangle(let width, let height):
            return width * height
        }
    }
    
    var perimeter: Double {
        switch self {
        case .circle(let radius):
            return 2 * Double.pi * radius
        case .rectangle(let width, let height):
            return 2 * (width + height)
        }
    }
}

let circle = Shape.circle(radius: 5)
print("面积: \(circle.area), 周长: \(circle.perimeter)")

6. 静态方法和属性

swift

复制代码
enum APIEndpoint {
    case users
    case posts
    case comments
    
    static var baseURL: String {
        return "https://api.example.com"
    }
    
    var path: String {
        switch self {
        case .users: return "/users"
        case .posts: return "/posts"
        case .comments: return "/comments"
        }
    }
    
    var url: String {
        return APIEndpoint.baseURL + self.path
    }
    
    static func endpoint(for string: String) -> APIEndpoint? {
        switch string {
        case "users": return .users
        case "posts": return .posts
        case "comments": return .comments
        default: return nil
        }
    }
}

let endpoint = APIEndpoint.users
print(endpoint.url)  // "https://api.example.com/users"

7. 协议遵循

swift

复制代码
// 遵循 CustomStringConvertible
enum NetworkError: Error, CustomStringConvertible {
    case noConnection
    case timeout(duration: TimeInterval)
    case serverError(code: Int, message: String)
    
    var description: String {
        switch self {
        case .noConnection:
            return "无网络连接"
        case .timeout(let duration):
            return "请求超时: \(duration)秒"
        case .serverError(let code, let message):
            return "服务器错误 \(code): \(message)"
        }
    }
}

// 遵循 CaseIterable(获取所有情况)
enum Direction: String, CaseIterable {
    case north = "北", south = "南", east = "东", west = "西"
}

print(Direction.allCases)  // [.north, .south, .east, .west]
for direction in Direction.allCases {
    print(direction.rawValue)
}

8. 高级模式匹配

if case 模式匹配

swift

复制代码
let response = NetworkResponse.success(data: Data(), statusCode: 200)

if case .success(let data, let code) = response {
    print("成功: 状态码 \(code), 数据长度 \(data.count)")
}

// 使用 where 子句
if case .failure(let error, let code) = response, code == 404 {
    print("404错误: \(error)")
}

guard case 模式匹配

swift

复制代码
func processResponse(_ response: NetworkResponse) {
    guard case .success(let data, 200...299) = response else {
        print("请求失败")
        return
    }
    
    print("处理数据: \(data.count) 字节")
}

9. 实际应用示例

状态管理

swift

复制代码
enum ViewState<T> {
    case idle
    case loading
    case loaded(T)
    case error(Error)
    
    var isLoading: Bool {
        if case .loading = self {
            return true
        }
        return false
    }
    
    var value: T? {
        if case .loaded(let value) = self {
            return value
        }
        return nil
    }
}

class ViewModel: ObservableObject {
    @Published var state: ViewState<[User]> = .idle
    
    func loadUsers() {
        state = .loading
        // 网络请求...
    }
}

配置管理

swift

复制代码
enum AppTheme: String, CaseIterable {
    case system = "系统"
    case light = "浅色"
    case dark = "深色"
    
    var userInterfaceStyle: UIUserInterfaceStyle {
        switch self {
        case .system: return .unspecified
        case .light: return .light
        case .dark: return .dark
        }
    }
}

enum AppLanguage: String, CaseIterable {
    case english = "en"
    case chinese = "zh"
    case japanese = "ja"
    
    var displayName: String {
        switch self {
        case .english: return "English"
        case .chinese: return "中文"
        case .japanese: return "日本語"
        }
    }
}

10. 最佳实践

使用枚举代替字符串常量

swift

复制代码
// ✅ 推荐
enum CellIdentifier {
    static let userCell = "UserCell"
    static let productCell = "ProductCell"
}

// ❌ 不推荐
let UserCellIdentifier = "UserCell"
let ProductCellIdentifier = "ProductCell"

使用枚举管理通知名

swift

复制代码
extension Notification.Name {
    static let userDidLogin = Notification.Name("UserDidLoginNotification")
    static let dataDidUpdate = Notification.Name("DataDidUpdateNotification")
}

// 使用
NotificationCenter.default.post(name: .userDidLogin, object: nil)

Swift 枚举的这些特性使其成为构建类型安全、表达力强的代码的强大工具。

相关推荐
m0_495562782 小时前
Swift-snapKit使用
开发语言·elasticsearch·swift
姓蔡小朋友2 小时前
Redis:Feed流、SortedSet实现点赞人排序、SortedSet滚动分页
java
青山的青衫2 小时前
【前后缀】Leetcode hot 100
java·算法·leetcode
q***46522 小时前
基于SpringBoot和PostGIS的各省与地级市空间距离分析
java·spring boot·spring
狂团商城小师妹2 小时前
JAVA国际版同城服务同城信息同城任务发布平台APP源码Android + IOS
android·java·ios
后端小张2 小时前
【JAVA 进阶】Spring Boot 自动配置原理与自定义 Starter 实战
java·spring boot·后端·spring·spring cloud·自定义·原理
Zzzzmo_2 小时前
Java数据结构:二叉树
java·数据结构·算法
CoovallyAIHub2 小时前
结构化数据迎来“ChatGPT时刻”!LimitX:一个模型统一所有表格任务
深度学习·算法·计算机视觉
多多*2 小时前
一个有 IP 的服务端监听了某个端口,那么他的 TCP 最大链接数是多少
java·开发语言·网络·网络协议·tcp/ip·缓存·mybatis