结构体的 Swift 枚举
Posted
技术标签:
【中文标题】结构体的 Swift 枚举【英文标题】:Swift Enum of a Struct 【发布时间】:2021-06-05 11:03:30 【问题描述】:在其他语言中,我可以构造复杂的枚举,它为每种情况保存多个值/一个类/一个结构。这在 Swift 中似乎是不可能的。至少我找不到一个简单的解决方案。到目前为止,我提出了这些可能性,其中包括一些样板文件,并且不像我习惯的其他语言那样优雅。
每种解决方案的缺点是什么?还有什么我可以做的吗?类会是更好的解决方案吗?
最后,我想要一个有限的、独特的、可迭代的不可变值构造。我希望这是一个枚举,因为它们通常有好处,比如知道它们何时被彻底匹配。
enum CategoryEnum: Int, CaseIterable
case general = 9
case tech = 5
var value: Category?
switch rawValue
case 9:
return Category(name: "General Knowledge", id: rawValue, symbol: Image(systemName: "globe"))
case 5:
return Category(name: "Technical", id: rawValue, symbol: Image(systemName: "internaldrive"))
default:
return nil // or throw error to ged rid of optional?
struct Category
static let GENERAL = Category(name: "General Knowledge", id: 9, symbol: Image(systemName: "globe"))
static let TECH = Category(name: "Technical", id: 5, symbol: Image(systemName: "internaldrive"))
static private let cases: [Int: Category] = [
GENERAL.id: GENERAL,
TECH.id: TECH
]
static func fromId(_ id: Int) -> Category?
Category.cases[id]
static func values() -> Dictionary<Int, Category>.Values
cases.values
let name: String
let id: Int
let symbol: Image
func testWithEnum()
// iterating over all cases
for cat in CategoryEnum.allCases
print(cat.value!.name)
// getting a case from the id
let catGen = CategoryEnum(rawValue: 9)
print(catGen!.value!.name)
// a specific case
print(CategoryEnum.general.value!.name)
func testWithStruct()
// iterating over all cases
for cat in Category.values()
print(cat.name)
// getting a case from the id
print(Category.fromId(9)!.name)
// a specific case
print(Category.TECH.name)
【问题讨论】:
【参考方案1】:我愿意:
enum Category: Int, CaseIterable
case general = 9
case tech = 5
var name: String
switch self
case .general: return "General Knowledge"
case .tech: return "Technical"
var symbol: Image
switch self
case .general: return Image(systemName: "globe")
case .tech: return Image(systemName: "internaldrive")
您可能不喜欢的一件事是,与您的结构解决方案相比,您无法一眼看出某个枚举案例的名称和符号。
请注意,每次向其中添加 case 时,都不会忘记向每个属性添加 return
语句,因为 switch 语句将不再是详尽无遗的,编译器会报错。
您不需要单独的 id
属性。这似乎只是原始价值。 init(rawValue:)
被合成是因为你有一个原始值,allCases
也是因为 CaseIterable
一致性而被合成的。
每种解决方案的缺点是什么?
您的枚举解决方案为其value
返回一个可选项,但显然每个案例必须 有一个与之关联的Category
,所以它没有多大意义。正如您在我的代码中看到的那样,您可以打开self
以使开关变得详尽。
您的 struct 解决方案不会阻止人们创建其他 Category
s,因此它不是您想要的“有限”。如果您想使用结构解决方案,您应该编写一个私有初始化程序来防止这种情况。此外,case
和 fromId
有很多样板文件。如果你使用枚举,那些是由编译器合成的。
【讨论】:
我认为这大致是我想要的,并且在语言的限制下是可能的。仍然不如其他语言优雅,但没有一种语言是完美的。感谢您帮助我。 @sbstnzmr 你在说什么语言能比这更有效?我现在想学那门语言:) 这不是全新的,我的措辞可能是错误的。应该没有写得更强大但不同。 Swift 和 Rust 有枚举,其中枚举可以有不同的类型。例如,Java 没有它,但它们有可以封装多个值的枚举。在此示例中,我不想将 enum 与某处的 Image 匹配。我希望将该图像封装在枚举中。也许只是我对 Swift 很陌生,这甚至不应该用枚举来完成。以上是关于结构体的 Swift 枚举的主要内容,如果未能解决你的问题,请参考以下文章