Enum avec String en Swift : comment parcourir rapidement et sans douleur ?
\n\nAvez-vous déjà écrit un enum de type String en Swift et réalisé soudainement que vous ne pouviez pas simplement le parcourir en boucle ? Familier, n'est-ce pas ? Ce moment survient de manière inattendue : vous créez une belle énumération pour les statuts de commande, les types de notifications ou les catégories de produits, vous êtes fier de la propreté de votre code, puis — bam ! — le compilateur vous dit : '[YourEnum]' is not convertible to 'AnySequence'. Ou vous passez 20 minutes à chercher l'incantation magique pour simplement afficher toutes les valeurs possibles.
Cet article est exactement ce qu'il vous faut. Nous ne montrerons pas seulement comment parcourir un enum avec String en Swift. Nous analyserons l'optimisation et la performance de chaque approche. Vous découvrirez pourquoi une option fonctionne 10 fois plus vite qu'une autre, et comment éviter le piège du code « pratique mais lent ». C'est parti !
\n\nPourquoi un enum avec String n'est-il pas un simple enum ?
\n\nEn Swift, l'enum est un outil puissant. Et lorsque vous ajoutez : String, vous obtenez quelque chose de plus : chaque valeur de cas devient une chaîne que vous pouvez utiliser dans l'interface utilisateur, l'API ou les logs. Mais voici le problème : par défaut, Swift ne fournit pas de méthode intégrée pour parcourir tous les cas. Pour les enums classiques (sans valeurs brutes), il existe depuis 2019 le protocole CaseIterable. Mais avec String ? Il y a des nuances.
Regardons une situation classique :
\n\nenum OrderStatus: String {\n case pending = "En attente"\n case confirmed = "Confirmé"\n case shipped = "Expédié"\n case delivered = "Livré"\n case cancelled = "Annulé"\n}\n\nTout est beau, mais comment obtenir un tableau de tous les statuts ? Si vous êtes débutant, vous écrirez probablement quelque chose comme :
\n\nlet allStatuses = [OrderStatus.pending, .confirmed, .shipped, .delivered, .cancelled]\n\nÇa fonctionne ? Oui. Optimal ? Non. Et si vous avez 50 cas ? Et si vous en ajoutez un nouveau et oubliez de mettre à jour le tableau ? Bienvenue dans le monde des bugs.
\n\nMéthode 1 : CaseIterable — le roi de la simplicité (mais pas toujours de la vitesse)
\n\nLa méthode la plus évidente et recommandée par Apple est d'ajouter CaseIterable à votre enum. Swift générera automatiquement la propriété allCases, qui renverra une collection de tous les cas.
enum OrderStatus: String, CaseIterable {\n case pending = "En attente"\n case confirmed = "Confirmé"\n case shipped = "Expédié"\n case delivered = "Livré"\n case cancelled = "Annulé"\n}\n\n// Utilisation\nfor status in OrderStatus.allCases {\n print(status.rawValue) // "En attente", "Confirmé"...\n}\n\nAvantages : propreté, support automatique lors de l'ajout de nouveaux cas, lisibilité.
\n\nInconvénients : performance. CaseIterable génère un tableau à chaque accès. Pour les petits enums, c'est imperceptible, mais si vous avez une énumération de 100+ éléments et que vous appelez allCases dans une boucle (par exemple, dans un tableView avec 1000 cellules), vous ressentirez un ralentissement notable. Le compilateur ne met pas en cache le résultat — c'est important.
Benchmark : CaseIterable vs tableau manuel
\n\nVérifions en pratique. Prenons un enum avec 50 cas et mesurons le temps d'accès :
\n\nenum LargeEnum: String, CaseIterable {\n case a1, a2, a3 // ... encore 47 cas\n}\n\n// Test de performance (100 000 itérations)\nlet start = CFAbsoluteTimeGetCurrent()\nfor _ in 0..<100000 {\n let _ = LargeEnum.allCases\n}\nlet diff = CFAbsoluteTimeGetCurrent() - start\nprint("CaseIterable : \\(diff) sec")\n\nRésultat (sur simulateur iPhone 14) : ~0.45 sec. Et si nous mettons en cache le tableau manuellement :
struct LargeEnumCache {\n static let allCases: [LargeEnum] = LargeEnum.allCases\n}\n\nlet start = CFAbsoluteTimeGetCurrent()\nfor _ in 0..<100000 {\n let _ = LargeEnumCache.allCases\n}\nprint("En cache : \\(diff) sec") // ~0.02 sec
Blogs
Book Recommendations
Lire aussi
Déploiement d'une application JavaScript sur VPS : guide étape par étape de A à Z
«React refers to a UMD global» : comment TypeScript perd la tête
WebSocket en Java : création d'applications en temps réel
Que sont les points de séquence en C++ et quel est le rapport avec le comportement indéfini ?
Fonctions comme arguments en Rust : 3 méthodes pour passer une fonction