以不透明的方式访问 swift 枚举数组中的关联值



我在相关问题中并没有真正找到我需要的东西。这可能是因为我有点厚,没有看到它,但这是我的窘境:

我有一个计算属性,它返回一个带有关联值的枚举数组。

这些值都是相同的类型(在我的用例中,类型是"标志"(,但枚举是不同的。

我想看看是否有某种方法可以在数组中循环,只查看关联的值,而不管枚举类型如何。我附上一个小游乐场,表明我的意思:

enum A {
case valueA(Int)
case valueB(Int)
case valueC(Int)
}
let a: [A] = [.valueA(0), .valueB(1), .valueC(2)]
for each in a {
print(String(describing: each))
}
print();
// This works:
for each in a {
if case let .valueA(value) = each {
print(value)
}
if case let .valueB(value) = each {
print(value)
}
if case let .valueC(value) = each {
print(value)
}
}
print();
// So does this:
for each in a {
var value: Int = 0
switch each {
case .valueA(let val):
value = val
case .valueB(let val):
value = val
case .valueC(let val):
value = val
}
print(value)
}
// What I want:
//for each in a {
//    if case let A(value) = each {
//        print(value)
//    }
//}

我希望能够处理集合的每个成员,并提取其标志,然后根据该标志做出决定。

我知道我可以用一个大的 ol' switch 语句来做到这一点,其中包含所有枚举值(第二次去(,但如果有一些通用方法来访问所有值,那就太好了。

您仍然需要针对每种情况进行测试,但您可以这样做

enum A {
case valueA(Int)
case valueB(Int)
case valueC(Int)
}
let a: [A] = [.valueA(0), .valueB(1), .valueC(2)]
for each in a {
switch each {
case .valueA(let val), .valueB(let val), .valueC(let val):
print(val)
}
}

如果您有具有不同类型的关联值的情况,这仍然适用:

enum Cases {
case one(Int)
case two(Int)
case three(Int, String)
case four(String)
case five(String)
}
let testArray = [Cases.one(1), .two(2), .three(3, "three"),
.four("four"), .five("five")]
// Matching associated Ints
for value in testArray {
switch value {
case .one(let intVal), .two(let intVal), .three(let intVal, _):
print(intVal)
case .four(let strVal), .five(let strVal):
print(strVal)
}
}
// Matching associated Strings
for value in testArray {
switch value {
case .one(let intVal), .two(let intVal):
print(intVal)
case .three(_, let strVal), .four(let strVal), .five(let strVal):
print(strVal)
}
}
// Matching any type, cast to Any
for value in testArray {
switch value {
case .one(let anyVal as Any), .five(let anyVal as Any):
print(anyVal)
default:
continue // skipping these cases
}
}

重要的一点是,您在尝试匹配其值的每个语句中绑定相同的 var 名称,这意味着您无法匹配 ever 语句中不可用的值:

switch ... {
// This won't work, because myInt is not defined in case .two 
// and myOtherInt isn't defined in case .one
case .one(let myInt), .two(let myOtherInt):
...
} 

为了补充@Kiril的答案,如果您希望为具有不同类型的关联值的情况计算值,则可以定义可选的计算变量来返回这些值:

extension Cases {
var intValue: Int? {
switch self {
case .one(let myInt), .two(let myInt), .three(let myInt, _):
return myInt
default:
return nil
}
}
var strValue: String? {
switch self {
case .three(_, let myStr), .four(let myStr), .five(let myStr):
return myStr
default:
return nil
}
}
}

我建议对您的枚举稍作修改:

enum A {
case valueA(Int)
case valueB(Int)
case valueC(Int)
var flag: Int {
switch self {
case .valueA(let flag),
.valueB(let flag),
.valueC(let flag):
return flag
}
}
}

这使得任何只需要标志的循环变得微不足道:

for each in a {
print(each.flag)
}

最新更新