enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
Par exemple, comment puis-je faire quelque chose comme:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
Exemple résultant:
♠
♥
♦
♣
Réponses:
Swift 4.2+
À partir de Swift 4.2 (avec Xcode 10), ajoutez simplement la conformité du protocole pour
CaseIterable
en bénéficierallCases
. Pour ajouter cette conformité au protocole, il vous suffit d'écrire quelque part:Si l'énumération est la vôtre, vous pouvez spécifier la conformité directement dans la déclaration:
Ensuite, le code suivant imprimera toutes les valeurs possibles:
Compatibilité avec les versions antérieures de Swift (3.x et 4.x)
Si vous devez prendre en charge Swift 3.x ou 4.0, vous pouvez imiter l'implémentation de Swift 4.2 en ajoutant le code suivant:
la source
String
, par opposition à la question actuelle Stack Overflow.Ce message est pertinent ici https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift
La solution proposée est essentiellement
la source
Enum.Values(typeof(FooEnum))
mais exposé comme une méthode d'extension (comme mapper ou réduire).FooEnum.values() :: values(EnumType -> [EnumType])
J'ai fait une fonction utilitaire
iterateEnum()
pour itérer les cas pour lesenum
types arbitraires .Voici l'exemple d'utilisation:
Quelles sorties:
Mais, c'est uniquement à des fins de débogage ou de test : cela repose sur plusieurs comportements de compilateur Swift1.1 non documentés, alors utilisez-le à vos risques et périls.
Voici le code:
L'idée sous-jacente est:
enum
, à l'exclusion deenum
s avec les types associés, n'est qu'un index des cas lorsque le nombre de cas est2...256
, il est identique àUInt8
, quand257...65536
, c'estUInt16
et ainsi de suite. Il peut donc provenirunsafeBitcast
de types entiers non signés correspondants..hashValue
des valeurs d'énumération est identique à l'indice du cas..hashValue
des valeurs d'énumération diffusées à partir d'un index non valide est0
.Révisé pour Swift2 et mis en œuvre des idées de casting à partir de la réponse de @ Kametrixom :
Révisé pour Swift3:
Révisé pour Swift3.0.1:
la source
withUnsafePointer
withMemoryRebound
et d'autrespointee
choses, utilisez-la par tous les moyens. Sinon, je l'éviterais.Les autres solutions fonctionnent mais elles font toutes des hypothèses, par exemple sur le nombre de rangs et de combinaisons possibles, ou sur ce que peuvent être le premier et le dernier rang. Certes, la disposition d'un jeu de cartes ne changera probablement pas beaucoup dans un avenir prévisible. En général, cependant, il est plus pratique d'écrire du code qui fait le moins d'hypothèses possible. Ma solution:
J'ai ajouté un type brut à l'
Suit
énumération, donc je peux utiliserSuit(rawValue:)
pour accéder auxSuit
cas:Ci-dessous l'implémentation de la
createDeck()
méthode Card .init(rawValue:)
est un initialiseur disponible et renvoie une option. En déballant et en vérifiant sa valeur dans les deux instructions while, il n'est pas nécessaire de supposer le nombreRank
ou lesSuit
cas:Voici comment appeler la
createDeck
méthode:la source
Suit
. Vous pouvez le faire dans cet exemple, mais l'exercice était destiné à vous amener à travailler avec les données quienums
vous ont été données comme si elles provenaient d'une source externe.Je suis tombé sur les bits et les octets et j'ai créé une extension dont j'ai découvert plus tard que les travaux étaient très similaires à la réponse de @rintaro . Il est utilisé comme ceci:
Ce qui est remarquable, c'est qu'il est utilisable sur n'importe quelle énumération sans valeurs associées. Notez que cela ne fonctionne pas pour les énumérations qui n'ont pas de cas.
Comme pour la réponse de @rintaro , ce code utilise la représentation sous-jacente d'une énumération. Cette représentation n'est pas documentée et pourrait changer à l'avenir, ce qui la briserait. Je ne recommande pas l'utilisation de ceci en production.
Code (Swift 2.2, Xcode 7.3.1, ne fonctionne pas sur Xcode 10):
Code (Swift 3, Xcode 8.1, ne fonctionne pas sur Xcode 10):
Je n'ai aucune idée pourquoi j'ai besoin
typealias
, mais le compilateur se plaint sans cela.la source
withUnsafePointer
…pointee}
bywithUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } }
Vous pouvez parcourir une énumération en implémentant le
ForwardIndexType
protocole.le
ForwardIndexType
protocole vous oblige à définir unesuccessor()
fonction pour parcourir les éléments.Itérer sur une plage ouverte ou fermée (
..<
ou...
) appellera en interne lasuccessor()
fonction qui vous permet d'écrire ceci:la source
successor()
méthode correctement définie (première option) éliminerait la nécessitéenum
d'avoir un type associé. +1Ce problème est maintenant beaucoup plus facile. Voici ma solution Swift 4.2:
Pré 4.2:
J'aime cette solution que j'ai mise en place après avoir trouvé " Compréhension de liste dans Swift ".
Il utilise Int raw au lieu de Strings mais il évite de taper deux fois, il permet de personnaliser les plages et ne code pas en dur les valeurs brutes.
Il s'agit d'une version Swift 4 de ma solution d'origine, mais voyez l'amélioration 4.2 ci-dessus:
la source
En principe, il est possible de le faire de cette façon en supposant que vous n'utilisez pas l'affectation de valeurs brutes pour les cas d'énumération:
la source
enum ItWontWorkForThisEnum {case a, b, c}
Si vous donnez à l'énumération une valeur Int brute, cela rendra la boucle beaucoup plus facile.
Par exemple, vous pouvez utiliser
anyGenerator
pour obtenir un générateur qui peut énumérer vos valeurs:Cependant, cela ressemble à un modèle assez courant, ne serait-ce pas bien si nous pouvions rendre n'importe quel type d'énumération énumérable en se conformant simplement à un protocole? Eh bien, avec Swift 2.0 et les extensions de protocole, nous le pouvons maintenant!
Ajoutez simplement ceci à votre projet:
Maintenant, chaque fois que vous créez une énumération (tant qu'elle a une valeur brute Int), vous pouvez la rendre énumérable en vous conformant au protocole:
Si vos valeurs d'énumération ne commencent pas par
0
(la valeur par défaut), remplacez lafirstRawValue
méthode:La dernière classe Suit, y compris le remplacement
simpleDescription
par le protocole CustomStringConvertible plus standard , ressemblera à ceci:Syntaxe Swift 3:
la source
Mise à jour vers Swift 2.2 +
C'est un code mis à jour au format Swift 2.2 @ réponse de Kametrixom
Pour Swift 3.0+ (merci à @Philip )
la source
Solution Swift 5:
la source
Je me suis retrouvé à faire
.allValues
beaucoup tout au long de mon code. J'ai finalement trouvé un moyen de simplement me conformer à unIteratable
protocole et d'avoir unerawValues()
méthode.la source
Xcode 10 avec Swift 4.2
Appeler
Tirages:
Versions plus anciennes
Pour
enum
représenterInt
Appelez ça comme ceci:
Tirages:
Pour
enum
représenterString
Appeler
Tirages:
la source
EDIT: Proposition Swift Evolution SE-0194 La collection dérivée de cas d'énumération propose une solution de niveau à ce problème. Nous le voyons dans Swift 4.2 et plus récent. La proposition souligne également certaines solutions de contournement qui sont similaires à certaines déjà mentionnées ici, mais il pourrait être intéressant de voir néanmoins.
Je conserverai également mon message d'origine par souci d'exhaustivité.
Il s'agit d'une autre approche basée sur la réponse de @ Peymmankh, adaptée à Swift 3 .
la source
Que dis-tu de ça?
la source
Vous pouvez essayer d'énumérer comme ceci
la source
static var enumerate = [Mercury, Venus, Earth, Mars]
, ce qui en fait une réponse médiocre par rapport à la réponse la plus votée stackoverflow.com/a/24137319/1033581return [Mercury, Venus, Mars]
place dereturn [Mercury, Venus, Earth, Mars]
return [.spades, .hearts, .clubs]
le compilateur ne dira rien et puis lorsque vous essayez de l'utiliser dans du code, vous obtiendrez[TestApp.Suit.spades, TestApp.Suit.hearts, TestApp.Suit.clubs]
- c'était mon point de vue - que si vous traitez avec un grand Enum et vous devez ajouter ou supprimer des cas de temps en temps, votre solution est sujette à des erreurs d'omission tandis que la réponse actuelle, bien que non concise, est plus sûre.Dans Swift 3, lorsque l'énumération sous-jacente a
rawValue
, vous pouvez implémenter leStrideable
protocole. Les avantages sont qu'aucun tableau de valeurs n'est créé comme dans certaines autres suggestions et que la boucle Swift "for in" standard fonctionne, ce qui fait une belle syntaxe.la source
Cette solution trouve le juste équilibre entre lisibilité et maintenabilité.
la source
Désolé, ma réponse était spécifique à la façon dont j'ai utilisé ce message dans ce que je devais faire. Pour ceux qui tombent sur cette question, à la recherche d'un moyen de trouver un cas dans une énumération, voici la façon de le faire (nouveau dans Swift 2):
Edit: minuscules camelCase est maintenant la norme pour les valeurs d'énumération Swift 3
Pour ceux qui s'interrogent sur l'énumération sur une énumération, les réponses données sur cette page qui incluent un var / let statique contenant un tableau de toutes les valeurs de l'énumération sont correctes. Le dernier exemple de code Apple pour tvOS contient exactement la même technique.
Cela étant dit, ils devraient construire un mécanisme plus pratique dans la langue (Apple, écoutez-vous?)!
la source
L'expérience était: EXPÉRIENCE
Ajoutez une méthode à la carte qui crée un jeu complet de cartes, avec une carte de chaque combinaison de rang et de couleur.
Donc, sans modifier ou améliorer le code donné autre que l'ajout de la méthode (et sans utiliser des choses qui n'ont pas encore été enseignées), j'ai trouvé cette solution:
la source
Voici une méthode que j'utilise pour à la fois itérer
enum
et fournir plusieurs types de valeurs à partir d'unenum
Voici la sortie:
Le numéro zéro en français: zéro, espagnol: cero, japonais: nuru
Le numéro un en français: un, espagnol: uno, japonais: ichi
Le numéro deux en français: deux, espagnol: dos, japonais: ni
Le numéro trois en français : trois, espagnol: tres, japonais: san
Le numéro quatre en français: quatre, espagnol: cuatro, japonais: shi
Le numéro cinq en français: cinq, espagnol: cinco, japonais: allez
Le numéro six en français: six, espagnol: seis, japonais: roku
The number Seven en français: sept, espagnol: siete, japonais: shichi
Total de 8 cas
siete en japonais: shichi
MISE À JOUR
J'ai récemment créé un protocole pour gérer l'énumération. Le protocole nécessite une énumération avec une valeur brute Int:
la source
Cela semble être un hack mais si vous utilisez des valeurs brutes, vous pouvez faire quelque chose comme ça
la source
Tout en traitant
Swift 2.0
ici est ma suggestion:J'ai ajouté le type brut à
Suit
enum
puis:
la source
Comme avec @Kametrixom, répondez ici je pense que le retour d'un tableau serait mieux que le retour d'AnySequence, car vous pouvez avoir accès à tous les avantages d'Array tels que le nombre, etc.
Voici la réécriture:
la source
Une autre solution:
la source
Ceci est un assez vieux post de Swift 2.0. Il existe maintenant de meilleures solutions ici qui utilisent les nouvelles fonctionnalités de swift 3.0: Itération via une énumération dans Swift 3.0
Et sur cette question, il existe une solution qui utilise une nouvelle fonctionnalité de (le pas encore publié au moment où j'écris cette modification) Swift 4.2: Comment puis-je obtenir le nombre d'une énumération Swift?
Il existe de nombreuses bonnes solutions dans ce fil et d'autres, mais certaines d'entre elles sont très compliquées. J'aime simplifier autant que possible. Voici une solution qui peut ou non fonctionner pour différents besoins mais je pense qu'elle fonctionne bien dans la plupart des cas:
Pour itérer:
la source
Les énumérations ont
toRaw()
et lesfromRaw()
méthodes. Donc, si votre valeur brute est unInt
, vous pouvez répéter du premier au dernierenum
:Un problème est que vous devez tester les valeurs facultatives avant d'exécuter la
simpleDescription
méthode.Nous définissons doncconvertedSuit
d'abord notre valeur, puis définissons une constante surconvertedSuit.simpleDescription()
la source
Voici mon approche suggérée. Ce n'est pas complètement satisfaisant (je suis très nouveau pour Swift et OOP!) Mais peut-être que quelqu'un peut l'affiner. L'idée est que chaque énumération fournisse ses propres informations de plage au fur
.first
et à mesure des.last
propriétés. Il ajoute seulement deux lignes de code à chaque énumération: toujours un peu codé en dur, mais au moins, il ne reproduit pas l'ensemble. Cela nécessite de modifier l'Suit
énumération pour être un Int comme l'Rank
énumération, au lieu de non typé.Plutôt que de faire écho à toute la solution, voici le code que j'ai ajouté à l'
.
énumération, quelque part après les déclarations de cas (l'Suit
énumération est similaire):et la boucle que j'ai utilisée pour construire le deck comme un tableau de String. (La définition du problème ne précisait pas comment le pont devait être structuré.)
Ce n'est pas satisfaisant car les propriétés sont associées à un élément plutôt qu'à l'énumération. Mais cela ajoute de la clarté aux boucles «for». J'aimerais qu'il dise
Rank.first
au lieu deRank.Ace.first
. Cela fonctionne (avec n'importe quel élément), mais c'est moche. Quelqu'un peut-il montrer comment élever cela au niveau énuméré?Et pour le faire fonctionner, j'ai retiré la
createDeck
méthode de la structure de la carte. Je ne pouvais pas comprendre comment obtenir un tableau [String] retourné à partir de cette structure, et cela semble de toute façon un mauvais endroit pour mettre une telle méthode.la source
Je l'ai fait en utilisant la propriété calculée, qui renvoie le tableau de toutes les valeurs (grâce à cet article http://natecook.com/blog/2014/10/loopy-random-enum-ideas/ ). Cependant, il utilise également des valeurs brutes int, mais je n'ai pas besoin de répéter tous les membres de l'énumération dans une propriété distincte.
UPDATE Xcode 6.1 a un peu changé la façon d'obtenir un membre enum
rawValue
, donc j'ai corrigé la liste. Correction également d'une petite erreur avec un mauvais premierrawValue
.la source
Basé sur la réponse de Rick: c'est 5 fois plus rapide
la source
Count
boîtier interrompra lesswitch
mises en œuvre et laCaseIterable
conformité exhaustives .