符合具有关联类型的协议的枚举类型数组

Array of enum types conforming to a protocol with an associated type

让我们考虑一个简化的情况,两个枚举类型符合 CaseIterable

enum A: String, CaseIterable {
    case a1, a2, a3
}

enum B: String, CaseIterable {
    case b1, b2, b3
}

我想要做的是创建某种散列 table 关联一个键(在我的例子中是一个字符串)和枚举的 类型

let dict: [String : CaseIterable.Type] = [ // Error here: Protocol 'CaseIterable' can only be used as a generic constraint because it has Self or associated type requirements
    "my key A" : A.self,
    "my key B" : B.self
]

我最终需要实现的是 "query" 我的散列 table 用于特定密钥,并对结果应用协议方法(比如 allCases)。

let cases = dict["my key A"]!.allCases

有什么建议吗?

I want to display a menu listing all the possible options.

所以你需要字符串,而不是案例本身。这是绝对可行的。首先,首先说明您真正希望该类型以协议的形式执行的操作:

protocol CaseNamed {
    static var caseNames: [String]
}

如果你有,你可以构建你想要的:

var enums: [CaseNamed.Type] = [A.self, B.self]
enums.flatMap { [=11=].caseNames }

(我称之为 "wish driven development." 我希望我有一个类型可以....)

现在您只需要通过实施 caseNames 使类型符合 CaseNamed。幸运的是,如果类型也恰好符合 CaseIterable:

extension CaseNamed where Self: CaseIterable {
    static var caseNames: [String] {
        self.allCases.map { "\([=12=])" }
    }
}

但是您可以使用不符合 CaseIterable 的 CaseNamed 类型。 CaseIterable 不是必需的。如果你有它就好了。这是完整的代码:

protocol CaseNamed {
    static var caseNames: [String] { get }
}

enum A: String, CaseIterable, CaseNamed {
    case a1, a2, a3
}

enum B: String, CaseIterable, CaseNamed {
    case b1, b2, b3
}

extension CaseNamed where Self: CaseIterable {
    static var caseNames: [String] {
        self.allCases.map { "\([=13=])" }
    }
}

var enums: [CaseNamed.Type] = [A.self, B.self]

enums.flatMap { [=13=].caseNames }

当然,您可能还希望此 CaseNamed 协议执行其他操作,因此您可以添加其他操作。但是您需要考虑调用代码以及它完成其工作的根本需要。