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 枚举的这些特性使其成为构建类型安全、表达力强的代码的强大工具。

相关推荐
爱丽_32 分钟前
深入理解 Java Socket 编程与线程池:从阻塞 I/O 到高并发处理
java·开发语言
济南壹软网络科技有限公司36 分钟前
云脉IM的高性能消息路由与离线推送机制摘要:消息的“零丢失、低延迟”之道
java·即时通讯源码·开源im·企业im
Seven9741 分钟前
剑指offer-46、孩⼦们的游戏(圆圈中最后剩下的数)
java
serendipity_hky1 小时前
互联网大厂Java面试故事:核心技术栈与场景化业务问题实战解析
java·spring boot·redis·elasticsearch·微服务·消息队列·内容社区
我真不会起名字啊1 小时前
C、C++中的sprintf和stringstream的使用
java·c语言·c++
十点摆码1 小时前
Spring Boot2 使用 Flyway 管理数据库版本
java·flyway·数据库脚本·springboo2·数据库脚本自动管理
资深web全栈开发1 小时前
LeetCode 3625. 统计梯形的数目 II
算法·leetcode·组合数学
橘颂TA1 小时前
【剑斩OFFER】算法的暴力美学——外观数列
算法·leetcode·职场和发展·结构与算法
Liangwei Lin1 小时前
洛谷 P1434 [SHOI2002] 滑雪
算法
毕设源码-钟学长1 小时前
【开题答辩全过程】以 基于Javaweb的电动汽车充电桩管理系统为例,包含答辩的问题和答案
java·spring boot