列出枚举中的所有案例
安全而不是简单
Swift语言的设计重点是“默认安全”方法(不要与“设计安全”混为一谈-Swift不会阻止您进行危险的动作,而只是鼓励良好的做法)。 这种激励措施之一是分别对sum和product数据类型enum
和struct
的大力支持。 这些类型很好地限制了编译期间潜在状态的数量,因此我们不必编写不应该发生的案例的任何单元测试-您绝对希望永远不要达到给定状态,而不是使用明显的单元测试来覆盖它。
问题陈述
尽管枚举在我们的工具箱中是非常强大的功能,但您可能会发现,没有简单安全的方法来列出enum
中的所有情况(当然,这是一个没有关联值的枚举)。 我遇到了一个问题,提出了一个UI选择器,其中包含用户可以选择的所有潜在状态(建模为枚举)。 我只需要一个数组,但是Swift不能立即提供它,而swift-evolving提案仍在等待轮流进行审查(详细讨论及其历史记录都在这里)。
解决方法
Swift社区经常建议两种解决方法来解决我的问题(灵感来自https://theswiftdev.com/2017/01/05/18-swift-gist-generic-allvalues-for-enums/):
- 使一个
enum
用Int
表示,并增加一个计数器,直到无法再创建案例为止:
- 将原始内存表示形式转换为枚举案例
这两种变通方法都不是理想的:首先假设开发人员为所有枚举分配后续值(从此处开始为1
),而第二种解决方案可能会在Swift更改枚举内存表示时中断(在Swift中我们仍然缺乏ABI稳定性)。
在本文中,我希望介绍另一种列出所有枚举实例的技术,该技术安全且独立于Swift实现细节。
TLDR;
为此,我们可以 为您的枚举 定义专用的 RawRepresentable
类型,并使该类型可通过 String
或 Int
文字表示。 请记住,如果我们尝试使用 init(rawValue:)
初始化一个枚举 ,则Swift会 init(rawValue:)
所有值 (具有相应的大小写),并将其与 rawValue
进行比较, 直到找到相等的值。 因此,如果我们尝试使用 任何不匹配任何大小写的 rawValue
进行初始化 ,我们将有机会在 ==
运算符实现中 收集具有相应枚举的所有rawValues 。