Generic function to get index of enum case from allCases

时间:2019-04-17 00:01:46

标签: swift indexing enums

I have a class with a property that is a case from an Enum. I want to write a generic function to get the index of the case in the Enum's allCases.

I begin by defining a protocol HasEnumCase which simply states that adopters have an associated CaseIterable & Equatable type.

protocol HasEnumCase {
    associatedtype TheEnum: CaseIterable & Equatable
    var theCase: TheEnum { get }
}

This does not compile.

func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int {
    let allCases = T.TheEnum.allCases
    let index = allCases.firstIndex(of: theInstance.theCase)
    return index
}

//Cannot convert return expression of type 'T.TheEnum.AllCases.Index' to return type 'Int'

It compiles when I am using a concrete type.

enum MyEnum: CaseIterable {
    case zero
    case one
}

class HasEnumClass {
    typealias E = MyEnum
    var myEnum: MyEnum = .one
}

let h = HasEnumClass()
let caseIndex = type(of: h.myEnum).allCases.firstIndex(of: h.myEnum)
// caseIndex = 1

2 个答案:

答案 0 :(得分:2)

The type Index defined on Collection doesn't have to be an Int, which is why you're seeing the error. You can use generic constraints to require this, though:

func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int where T.TheEnum.AllCases.Index == Int {
    // ...
}

答案 1 :(得分:0)

daltonclaybrook's reasoning and answer is correct: the issue is the type of Index.

I found I can also create an array from the result of allCases and the compiler will do the rest.

func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int {
    let allCases = Array(type(of: theInstance).TheEnum.allCases)
    let index = allCases.firstIndex(of: theInstance.theCase)!
    return index
}