Самоанализ и итерация в Enum

Можно ли программно узнать, сколько «случаев» Enum имеет в Swift 2, и перебрать их?

Этот код не компилируется, но дает представление о том, чего я пытаюсь достичь:

enum HeaderStyles{

    case h1
    case h2
    case h3
}

for item in HeaderStyles{
    print(item)
}

person cfischer    schedule 25.08.2015    source источник
comment
Перечисления должны быть объявлены во время компиляции, поэтому вы - разработчик - точно знаете, сколько случаев имеет перечисление. ;-)   -  person vadian    schedule 25.08.2015
comment
У меня есть ответ, который вы можете найти здесь stackoverflow.com/a/48960126/5372480   -  person MSimic    schedule 23.03.2018


Ответы (2)


Вы можете написать общую структуру, которая обеспечивает эту возможность итерации. В приведенном ниже примере необработанные значения перечисления должны начинаться с 0 (это происходит по умолчанию) и не иметь пробелов между необработанными значениями (не могут иметь необработанные значения, такие как 0,1,2,3,5 - 4 отсутствует)

public struct EnumGenerator<T> : GeneratorType, SequenceType {
    private let enumInit: Int -> T?
    private var i: Int = 0
    public mutating func next() -> T? { return enumInit(i++) }
    public init(_ initFunc: Int -> T?){ self.enumInit = initFunc}
}

enum HeaderStyles:Int{
    case h1
    case h2
    case h3
}

for item in EnumGenerator(HeaderStyles.init){
    print(item)
}
person yshilov    schedule 06.09.2015

Самый простой способ перебрать все случаи — создать вычисляемое свойство, которое возвращает Array из них:

enum SomeEnum {
    case Zero, One, Two

    static var allCases: [SomeEnum] {
        return [.Zero, .One, .Two]
    }
}

Если вам нужен автоматический массив, вы можете использовать Int как rawValue, поэтому вам не нужно менять какой-либо код, если вы добавите дополнительный case:

Swift 3/4: ++ и -- удалены, а anyGenerator переименовано в AnyIterator.

enum SomeEnum: Int {
    case Zero, One, Two

    static var allCases: [SomeEnum] {
        var i = 0
        return Array(AnyIterator{
            let newEnum = SomeEnum(rawValue: i)
            i += 1
            return newEnum
        })
    }
}

Свифт 2

enum SomeEnum: Int {
    case Zero, One, Two

    static var allCases: [SomeEnum] {
        var i = 0
        return Array(anyGenerator{ SomeEnum(rawValue: i++) })
    }
}

В обоих случаях вы должны использовать его следующим образом:

for num in SomeEnum.allCases {
    // ...
}
person Qbyte    schedule 25.08.2015