在 Swift 中,枚举的作用是非常强大的,除了定义固定的离散值,它还能承载关联值、原始值、方法,甚至遵守协议,是构建类型安全 API 的关键工具之一。
什么是枚举(Enum)
枚举用于表示一组有穷且明确的值,比如状态、类型、分类等。例如 HTTP 状态码、用户角色、订单状态等。
enum UserRole {
case admin, member, guest
}
相比用字符串或整数,枚举更加类型安全、可维护、可拓展。
定义枚举的基本语法
enum DeviceType {
case iPhone
case iPad
case mac
}
可以使用点语法访问枚举值:
let device: DeviceType = .iPhone
原始值
如果你想让每个枚举 case 对应一个 String 或 Int 值,可以添加原始值类型:
enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
}
访问:
let method = HTTPMethod.get.rawValue // "GET"
还可以通过原始值初始化:
let method = HTTPMethod(rawValue: "POST") // Optional(.post)
关联值
关联值允许枚举在不同 case 下携带不同类型的附加数据:
enum APIResponse {
case success(data: Data)
case failure(error: String)
}
使用:
let response = APIResponse.success(data: Data())
结合 switch 解包数据:
switch response {
case .success(let data):
print("Received (data.count) bytes")
case .failure(let error):
print("Error: (error)")
}
遍历所有枚举值
使用 CaseIterable 可以轻松访问枚举的所有 case,常用于 UI 列表:
enum Direction: String, CaseIterable {
case north, south, east, west
}
for dir in Direction.allCases {
print(dir.rawValue)
}
注意:**带关联值的枚举无法自动遵守 CaseIterable。
SwiftUI 中使用枚举
在 SwiftUI 中,枚举是构建 TabView 等组件的理想选择。
enum Tab: String, CaseIterable, Identifiable {
case home, profile, settings
var id: String { rawValue }
}
TabView {
ForEach(Tab.allCases) { tab in
Text("This is (tab.rawValue.capitalized)")
.tabItem { Text(tab.rawValue.capitalized) }
}
}
枚举与 Equatable / Hashable
不带关联值的枚举默认遵守 Equatable 和 Hashable。带关联值时:
enum Result: Equatable {
case success(data: Int)
case failure(code: Int)
}
Swift 会合成 ==,前提是所有关联值类型也要是 Equatable。
模式匹配
快速匹配枚举 case 而无需写完整 switch:
if case .success(let data) = response {
print(data)
}
或用于逻辑提前退出:
guard case .success(let data) = response else {
return
}
枚举中添加方法和计算属性
枚举不只是静态值,还可以封装行为:
enum Language {
case swift, kotlin, dart
var isStronglyTyped: Bool {
switch self {
case .swift, .kotlin: return true
case .dart: return false
}
}
func helloWorld() -> String {
switch self {
case .swift: return "Hello,Swift"
case .kotlin: return "Hello,Kotlin"
case .dart: return "Hello,Dart"
}
}
}
比如上面的代码,我们可以给枚举添加计算属性和函数。
使用 OptionSet 替代“多选枚举”
当你需要表示多个可组合的选项(如权限、标志)时,枚举就不太合适了,可以使用 OptionSet来实现:
struct Permission: OptionSet {
let rawValue: Int
static let read = Permission(rawValue: 1 << 0)
static let write = Permission(rawValue: 1 << 1)
static let exec = Permission(rawValue: 1 << 2)
}
let access: Permission = [.read, .exec]
总结
Swift 枚举远比 Objective-C 中的枚举更加强大。在 Swift 中编写代码时,枚举是一个强大的工具。它提高了代码可读性,同时可以让你享受到编译时安全性。你可以使用 CaseIterable 协议和自定义原始值创建动态代码解决方案。默认情况下,枚举是可比较的,除非你添加了关联值。