枚举在 Swift 中是一种将一组相关值统一在一个名称下的类型。与 C 和 Objective-C 不同,其中枚举仅仅是整数常量的集合,Swift 提供了第一类枚举,具有关联值、原始值、方法和协议支持。根据 Apple, 2026,枚举是 iOS 开发中类型安全状态建模的关键工具之一。
要点
枚举是一种用户定义的数据类型,它组合了一组有限的互斥变体。在 Swift 中,枚举不仅仅是数字常量,而是一个拥有自身逻辑的完整类型。
枚举的每个变体称为 case。与 Objective-C 不同,其中枚举被简化为整数类型,Swift 允许每个 case 存储自己的数据并拥有方法。
根据 Apple,Swift 中的枚举支持泛型、初始化器、计算属性和协议实现 — 这使得它适用于状态、错误、选项和有限状态机的建模。
在任何需要表示有限集合的互斥变体时使用枚举:屏幕状态、错误类型、方向、筛选选项。
枚举使用关键字 enum 后跟名称和花括号中的主体来声明。
enum CompassDirection {
case north
case south
case east
case west
}
Case 可以用逗号在一行中声明:
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
要访问 case,在已知类型后使用点语法:
let direction = CompassDirection.north
// 已知类型 — 可使用简写语法:
var currentPlanet = .earth
在将变量赋值给已知的枚举类型后,Swift 会自动推断类型,访问 case 时可以省略枚举名称。
原始值是分配给枚举每个 case 的相同类型的值。与关联值不同,原始值对所有 case 类型相同,并在声明时设置。
enum HTTPStatusCode: Int {
case ok = 200
case notFound = 404
case internalServerError = 500
}
let code = HTTPStatusCode.notFound
print(code.rawValue) // 404
对于整数原始值,如果只显式指定了第一个,Swift 会自动递增值:
enum Status: Int {
case pending = 1
case active // 2
case completed // 3
}
原始值可以是 Int、String、Character 或任何符合 RawRepresentable 协议的类型。Swift 会自动生成初始化器 init? 以从原始值创建枚举 — 这在解析 API 数据时非常方便。
关联值允许将不同的数据类型单独附加到枚举的每个 case。与原始值不同,关联值可以在类型和数量上有所不同。
enum NetworkError {
case timeout(seconds: Int)
case httpError(code: Int, message: String)
case noConnection
case unknown(error: Error)
}
通过 switch 处理时,关联值通过绑定到变量或常量来提取:
let error = NetworkError.httpError(code: 403, message: "Forbidden")
switch error {
case .timeout(let seconds):
print("\(seconds)s 后超时")
case .httpError(let code, let message):
print("HTTP \(code): \(message)")
case .noConnection:
print("无连接")
case .unknown(let err):
print("未知:\(err.localizedDescription)")
}
根据 Apple 文档,关联值使枚举成为建模复杂状态的表达性工具,无需创建单独的包装类型。将它们用于类似 Result 的场景和带有上下文的错误建模。
递归枚举 — 其 case 引用枚举类型本身的枚举。这样的 case 用关键字 indirect 标记。
indirect enum LinkedList<T> {
case empty
case node(value: T, next: LinkedList<T>)
}
关键字 indirect 在 enum 之前将所有 case 标记为递归。或者,可以仅用 indirect 标记特定 case:
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
Swift 使用 indirect 将递归 case 存储为引用(引用语义)而不是值 — 这避免了枚举在栈上的无限大小。递归枚举广泛用于构建树、链表和 AST。
枚举可以像结构体和类一样实现协议。这是 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"
}
}
}
枚举还可以实现 Cocoa 协议 — 例如,CaseIterable 用于自动生成所有 case 的集合,或 Codable 用于序列化。这使得枚举成为 Swift 应用程序中的通用构建块。
常见问题
枚举是具有有限互斥变体集的类型,而结构体是具有任意属性集的类型。枚举不能有存储属性,但支持计算属性和方法。
不可以,枚举不能同时拥有原始值和关联值。原始值是所有 case 的相同类型的值,关联值是每个 case 的单独数据。这些机制是互斥的。
添加对 CaseIterable 协议的遵守。Swift 会自动生成属性 allCases,它按声明顺序返回所有 case 的集合。这便于遍历所有变体。
Switch 是最安全的方法,因为编译器会检查穷尽覆盖。可以使用 if case 检查单个 case,或对没有关联值的枚举使用 ==。
是的,枚举支持泛型:enum Result<T, E> { case success(T); case failure(E) }。这允许创建类型安全的通用结构来处理成功和错误。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。