Enum mit String in Swift durchlaufen: Leistung und Optimierung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Enum mit String in Swift: Wie durchläuft man schnell und schmerzfrei?

\n\n

Haben Sie jemals ein Enum mit dem Typ String in Swift geschrieben und plötzlich festgestellt, dass Sie es nicht einfach in einer Schleife durchlaufen können? Kommt Ihnen bekannt vor, oder? Dieser Moment kommt unerwartet: Sie erstellen eine schöne Aufzählung für Bestellstatus, Benachrichtigungstypen oder Produktkategorien, sind stolz auf den sauberen Code, und dann – zack! – sagt der Compiler: '[YourEnum]' is not convertible to 'AnySequence'. Oder Sie verbringen 20 Minuten damit, nach einem magischen Befehl zu suchen, um einfach alle möglichen Werte auszugeben.

\n\n

Dieser Artikel ist genau das, was Sie brauchen. Wir zeigen nicht nur, wie man ein Enum mit String in Swift durchläuft. Wir analysieren Optimierung und Leistung jedes Ansatzes. Sie erfahren, warum eine Variante 10-mal schneller ist als eine andere und wie Sie nicht in die Falle von „bequemem, aber langsamem“ Code tappen. Los geht's!

\n\n

Warum ist ein Enum mit String mehr als nur ein Enum?

\n\n

In Swift ist ein Enum ein mächtiges Werkzeug. Wenn Sie : String hinzufügen, erhalten Sie etwas noch Größeres: Jeder Fallwert wird zu einem String, den Sie in der UI, API oder in Logs verwenden können. Aber hier ist der Haken: Standardmäßig bietet Swift keine eingebaute Möglichkeit, alle Fälle zu durchlaufen. Für normale Enums (ohne Raw Values) gibt es seit 2019 das Protokoll CaseIterable. Aber bei String? Da gibt es Nuancen.

\n\n

Schauen wir uns eine klassische Situation an:

\n\n
enum OrderStatus: String {\n    case pending = "Wartend"\n    case confirmed = "Bestätigt"\n    case shipped = "Versendet"\n    case delivered = "Geliefert"\n    case cancelled = "Storniert"\n}
\n\n

Alles schön, aber wie erhält man ein Array aller Status? Wenn Sie ein Anfänger sind, schreiben Sie wahrscheinlich so etwas wie:

\n\n
let allStatuses = [OrderStatus.pending, .confirmed, .shipped, .delivered, .cancelled]
\n\n

Funktioniert es? Ja. Optimal? Nein. Was, wenn Sie 50 Fälle haben? Was, wenn Sie einen neuen hinzufügen und vergessen, das Array zu aktualisieren? Willkommen in der Welt der Fehler.

\n\n

Methode 1: CaseIterable – König der Einfachheit (aber nicht immer der Geschwindigkeit)

\n\n

Der offensichtlichste und von Apple empfohlene Weg ist, CaseIterable zu Ihrem Enum hinzuzufügen. Swift generiert automatisch die Eigenschaft allCases, die eine Sammlung aller Fälle zurückgibt.

\n\n
enum OrderStatus: String, CaseIterable {\n    case pending = "Wartend"\n    case confirmed = "Bestätigt"\n    case shipped = "Versendet"\n    case delivered = "Geliefert"\n    case cancelled = "Storniert"\n}\n\n// Verwendung\nfor status in OrderStatus.allCases {\n    print(status.rawValue) // "Wartend", "Bestätigt"...\n}
\n\n

Vorteile: Sauberkeit, automatische Unterstützung beim Hinzufügen neuer Fälle, Lesbarkeit.

\n\n

Nachteile: Leistung. CaseIterable generiert bei jedem Zugriff ein Array. Bei kleinen Enums ist das unbemerkt, aber wenn Sie eine Aufzählung mit 100+ Elementen haben und allCases in einer Schleife aufrufen (z. B. in einer tableView mit 1000 Zellen), erhalten Sie eine spürbare Verzögerung. Der Compiler speichert das Ergebnis nicht zwischen – das ist wichtig.

\n\n

Benchmark: CaseIterable vs. manuelles Array

\n\n

Lassen Sie uns das in der Praxis überprüfen. Nehmen wir ein Enum mit 50 Fällen und messen die Zugriffszeit:

\n\n
enum LargeEnum: String, CaseIterable {\n    case a1, a2, a3 // ... weitere 47 Fälle\n}\n\n// Leistungstest (100.000 Iterationen)\nlet start = CFAbsoluteTimeGetCurrent()\nfor _ in 0..<100000 {\n    let _ = LargeEnum.allCases\n}\nlet diff = CFAbsoluteTimeGetCurrent() - start\nprint("CaseIterable: \\(diff) Sek.")
\n\n

Ergebnis (auf iPhone 14 Simulator): ~0,45 Sek.. Und wenn wir das Array manuell zwischenspeichern:

\n\n
struct LargeEnumCache {\n    static let allCases: [LargeEnum] = LargeEnum.allCases\n}\n\nlet start = CFAbsoluteTimeGetCurrent()\nfor _ in 0..<100000 {\n    let _ = LargeEnumCache.allCases\n}\nprint("Zwischengespeichert: \\(diff) Sek.") // ~0,02 Sek.

                
                

Blogs

Buchempfehlungen