我认为我最喜欢 Swift 4.2 的可能是编译器自动为枚举生成一个 allCases 的集合。
如何知道在我的枚举里有多少个 Case
知道一个枚举有多少种情况或者去迭代所有的情况这通常是很有用的。在 Swift4.2 之前,你也许使用一个元编程工具例如Sourcery或者手动的维护这个集合
1 | enum Direction { |
2 | case left |
3 | case right |
4 | } |
5 | |
6 | extension Direction { |
7 | static let allItems: [Direction] = [.left, .right] |
8 | } |
9 | |
10 | Direction.allItems.count |
11 | // 2 |
12 | Direction.allItems.forEach { print($0) } |
13 | // left |
14 | // right |
手动维护是痛苦的,而且当我为枚举添加额外的 Cases,而忘记更新 allItems 的实现时,他无法按照预期工作
1 | enum Direction { |
2 | case left |
3 | case right |
4 | case up |
5 | case down |
6 | } |
7 | |
8 | Direction.allItems.count |
9 | // 2 ??? |
CaseIterable 协议
Swift4.2 为我们带来了 CaseIterable 协议。他们像Equatable,Comparable和Hashable都是通过编译器自动合成来实现的
你需要做的就是声明你的枚举遵循这个协议
1 | enum Direction: CaseIterable { |
2 | case left |
3 | case right |
4 | case up |
5 | case down |
6 | } |
编译器提供给你一个包含所有情况叫做allCases的集合
1 | Direction.allCases.count |
2 | // 4 |
3 | Direction.allCases.forEach { print($0) } |
4 | // left right up down. |
注意:
- 集合的顺序遵循枚举声明的顺序。
- 编译器不会自动为具有关联值得枚举合成
allCases的实现,因为他可能具有无限数量的情况 - 文档中仍然要求你必须定义枚举的时候遵循这个协议,但在 Swift4.2 中不再是这样,只要在同一个文件中,就可以在扩展中声明一致性:
swift4.2 之后
1 | enum Direction { ... } |
2 | extension Direction: CaseIterable {} |
swift4.2 之前
1 | enum Direction: CaseIterable { ... } |
- 你可以自己实现 CaseIterable 协议,缺点是如果有人向枚举添加新的 case,那么你将维护返回的实现并使其保持最新状态