607 Stimmen

Wie nummeriert man einen Aufzählungstyp mit String-Typ?

enum Suit: String {
    case spades = ""
    case hearts = ""
    case diamonds = ""
    case clubs = ""
}

Zum Beispiel, wie kann ich so etwas machen:

for suit in Suit {
    // Bearbeite etwas mit dem Anzug
    print(suit.rawValue)
}

Ergebnisbeispiel:

12voto

ale_stro Punkte 806

Aktualisiert auf Swift 2.2+

func iterateEnum(_: T.Type) -> AnyGenerator {
    var i = 0
    return AnyGenerator {
        let next = withUnsafePointer(&i) {
            UnsafePointer($0).memory
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

Es handelt sich um aktualisierten Code für Swift 2.2 aus @Kametrixom's Antwort

Für Swift 3.0+ (vielen Dank an @Philip)

func iterateEnum(_: T.Type) -> AnyIterator {
    var i = 0
    return AnyIterator {
        let next = withUnsafePointer(&i) {
            UnsafePointer($0).pointee
        }
        if next.hashValue == i {
            i += 1
            return next
        } else {
            return nil
        }
    }
}

12voto

Jochen Holzer Punkte 1379

Swift 5 Lösung:

enum Suit: String, CaseIterable {
    case spades = ""
    case hearts = ""
    case diamonds = ""
    case clubs = ""
}

// Fälle können wie folgt zugegriffen werden:

for suitKey in Suit.allCases {
    print(suitKey)
}

10voto

Warif Akhand Rishi Punkte 23036

Xcode 10 mit Swift 4.2

enum Filter: String, CaseIterable {

    case salary = "Gehalt"
    case experience = "Erfahrung"
    case technology = "Technologie"
    case unutilized = "Nicht genutzt"
    case unutilizedHV = "Nicht genutzt High Value"

    static let allValues = Filter.allCases.map { $0.rawValue }
}

Rufen Sie es auf

print(Filter.allValues)

Druckt:

["Gehalt", "Erfahrung", "Technologie", "Nicht genutzt", "Nicht genutzt High Value"]


Ältere Versionen

Für enum das Int darstellt

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // Erstes bis letztes Case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.rawValue }
}

Rufen Sie es wie folgt auf:

print(Filter.allValues)

Druckt:

[0, 1, 2, 3, 4]


Für enum das String darstellt

enum Filter: Int {
    case salary
    case experience
    case technology
    case unutilized
    case unutilizedHV

    static let allRawValues = salary.rawValue...unutilizedHV.rawValue  // Erstes bis letztes Case
    static let allValues = allRawValues.map { Filter(rawValue: $0)!.description }
}

extension Filter: CustomStringConvertible {
    var description: String {
        switch self {
        case .salary: return "Gehalt"
        case .experience: return "Erfahrung"
        case .technology: return "Technologie"
        case .unutilized: return "Nicht genutzt"
        case .unutilizedHV: return "Nicht genutzt High Value"
        }
    }
}

Rufen Sie es auf

print(Filter.allValues)

Druckt:

["Gehalt", "Erfahrung", "Technologie", "Nicht genutzt", "Nicht genutzt High Value"]

7voto

Fabian Buentello Punkte 532

Ich habe festgestellt, dass ich in meinem Code oft .allValues verwendet habe. Ich habe schließlich einen Weg gefunden, um einfach einem Iteratable Protokoll zu entsprechen und eine rawValues() Methode zu haben.

protocol Iteratable {}
extension RawRepresentable where Self: RawRepresentable {

    static func iterateEnum(_: T.Type) -> AnyIterator {
        var i = 0
        return AnyIterator {
            let next = withUnsafePointer(to: &i) {
                $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
            }
            if next.hashValue != i { return nil }
            i += 1
            return next
        }
    }
}

extension Iteratable where Self: RawRepresentable, Self: Hashable {
    static func hashValues() -> AnyIterator {
        return iterateEnum(self)
    }

    static func rawValues() -> [Self.RawValue] {
        return hashValues().map({$0.rawValue})
    }
}

// Beispiel
enum Grocery: String, Iteratable {
    case Kroger = "kroger"
    case HEB = "h.e.b."
    case Randalls = "randalls"
}

let groceryHashes = Grocery.hashValues() // AnyIterator
let groceryRawValues = Grocery.rawValues() // ["kroger", "h.e.b.", "randalls"]

7voto

ff10 Punkte 2956

BEARBEITEN: Swift Evolution Vorschlag SE-0194 Abgeleitete Sammlung von Enum-Fällen schlägt eine vernünftige Lösung für dieses Problem vor. Wir sehen es in Swift 4.2 und neuer. Der Vorschlag weist auch auf einige Workarounds hin, die ähnlich sind wie einige hier bereits erwähnte, aber es könnte dennoch interessant sein, sie zu sehen.

Ich werde auch meinen ursprünglichen Beitrag der Vollständigkeit halber behalten.


Dies ist ein weiterer Ansatz basierend auf der Antwort von @Peymmankh, angepasst an Swift 3.

public protocol EnumCollection: Hashable {}

extension EnumCollection {

public static func allValues() -> [Self] {
    typealias S = Self

    let retVal = AnySequence { () -> AnyIterator in
        var raw = 0
        return AnyIterator {
            let current = withUnsafePointer(to: &raw) {
                 $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
            }
            guard current.hashValue == raw else { return nil }
            raw += 1
            return current
        }
    }

    return [S](retVal)
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X