CaseIterable 是 Swift 标准库中的一个协议,用于自动生成枚举中所有可能的值集合。它非常适合用来处理需要遍历枚举值的场景,例如在 Picker 中显示选项列表,或者在循环中遍历所有枚举值。
协议定义
CaseIterable 定义如下:
protocol CaseIterable {
associatedtype AllCases: Collection where Self.AllCases.Element == Self
static var allCases: Self.AllCases { get }
}
核心功能:
提供一个静态属性 allCases,返回枚举中所有可能值的集合。
如何让枚举遵循 CaseIterable
1、自动生成 allCases 属性
当枚举不包含关联值时,Swift 会自动为其生成 allCases 属性。
enum Direction: CaseIterable {
case north
case south
case east
case west
}
// 自动生成的 allCases:
// Direction.allCases == [Direction.north, Direction.south, Direction.east, Direction.west]
2、带原始值的枚举
包含原始值(如 String 或 Int)的枚举仍然可以自动支持 CaseIterable。
enum Fruit: String, CaseIterable {
case apple = "Apple"
case banana = "Banana"
case cherry = "Cherry"
}
// Fruit.allCases == [Fruit.apple, Fruit.banana, Fruit.cherry]
3、手动实现 allCases
如果枚举有关联值,则需要手动实现 allCases 属性。
这是因为关联值使得枚举的所有可能性无法被自动推导。
enum Shape: CaseIterable {
static var allCases: [Shape] = [.circle, .square]
case circle
case square
case rectangle(width: Double, height: Double)
}
使用场景
1、遍历枚举所有值
enum Day: CaseIterable {
case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
for day in Day.allCases {
print(day)
}
输出:
monday
tuesday
wednesday
thursday
friday
saturday
Sunday
2、在 SwiftUI 中生成选项列表
struct ContentView: View {
@State private var selectedDay: Day = .monday
var body: some View {
Picker("Select a Day", selection: $selectedDay) {
ForEach(Day.allCases, id: \.self) { day in
Text(day.displayName).tag(day)
}
}
.pickerStyle(.segmented)
}
}
enum Day: String, CaseIterable {
case monday, tuesday, wednesday, thursday, friday, saturday, sunday
var displayName: String {
rawValue.capitalized
}
}
效果:
一个选择器,显示所有天数供用户选择。
3、用作数据驱动
enum PaymentMethod: CaseIterable {
case creditCard, paypal, applePay
var description: String {
switch self {
case .creditCard: return "Credit Card"
case .paypal: return "PayPal"
case .applePay: return "Apple Pay"
}
}
}
let methods = PaymentMethod.allCases.map { $0.description }
print(methods) // ["Credit Card", "PayPal", "Apple Pay"]
注意事项
1、关联值限制
带关联值的枚举无法自动实现 allCases,需要手动提供。
2、大型枚举性能
allCases 返回的是一个数组,对非常大的枚举使用时可能会带来性能开销。
总结
CaseIterable 是用于遍历枚举所有可能值的强大工具,尤其在 SwiftUI 和数据驱动场景中非常常用。
自动支持无关联值的枚举;对于有关联值的枚举,需要手动实现。
搭配 ForEach 和 Picker 可以简化代码,提高可读性和开发效率。