Comment puis-je déterminer le nombre d'observations dans une énumération Swift?
(Je voudrais éviter d' énumérer manuellement toutes les valeurs , ou d'utiliser le vieux « truc enum_count » si possible.)
Comment puis-je déterminer le nombre d'observations dans une énumération Swift?
(Je voudrais éviter d' énumérer manuellement toutes les valeurs , ou d'utiliser le vieux « truc enum_count » si possible.)
Depuis Swift 4.2 (Xcode 10), vous pouvez déclarer la conformité au CaseIterable
protocole, cela fonctionne pour toutes les énumérations sans valeurs associées:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
Le nombre de cas est maintenant obtenu simplement avec
print(Stuff.allCases.count) // 4
Pour plus d'informations, consultez
J'ai un article de blog qui va plus en détail à ce sujet, mais tant que le type brut de votre énumération est un entier, vous pouvez ajouter un décompte de cette façon:
la source
case A=1, B=3
?enum
avoir uneInt
valeur brute que vous avez oublié de mentionner: les énumérations Swift avec des valeurs brutes Int n'ont pas à commencer à partir de 0 (même si c'est le comportement par défaut) et leurs valeurs brutes peuvent être arbitraires, elles n'ont pas pour incrémenter de 1 (même si c'est le comportement par défaut).Mise à jour Xcode 10
Adoptez le
CaseIterable
protocole dans l'énumération, il fournit uneallCases
propriété statique qui contient tous les cas d'énumération sous forme de fichierCollection
. Utilisez simplement sacount
propriété pour savoir combien de cas l'énumération a.Voir la réponse de Martin pour un exemple (et voter pour ses réponses plutôt que les miennes)
avertissement : la méthode ci-dessous ne semble plus fonctionner.
Je ne connais aucune méthode générique pour compter le nombre de cas d'énumération. J'ai cependant remarqué que la
hashValue
propriété des cas enum est incrémentale, à partir de zéro, et avec l'ordre déterminé par l'ordre dans lequel les cas sont déclarés. Ainsi, le hachage de la dernière énumération plus un correspond au nombre de cas.Par exemple avec cette énumération:
count
renvoie 4.Je ne peux pas dire si c'est une règle ou si cela changera un jour, alors utilisez à vos risques et périls :)
la source
hashValues
ces choses; tout ce que nous savons, c'est qu'il s'agit d'une valeur unique aléatoire - pourrait changer très facilement à l'avenir en fonction de certains détails d'implémentation du compilateur; mais dans l'ensemble, le manque de fonctionnalité de comptage intégrée est inquiétant.case ONE = 0
, vous pouvez alors remplacerhashValue
parrawValue
.static var count = 4
plutôt que de laisser votre destin dans le sort des futures implémentations de SwiftJe définis un protocole réutilisable qui effectue automatiquement le décompte des cas en fonction de l'approche publiée par Nate Cook.
Ensuite, je peux réutiliser ce protocole par exemple comme suit:
la source
count++
decount+=1
car la++
notation sera supprimée dans Swift 3static var caseCount: Int { get }
? pourquoi le besoin de l 'static func
?case A=1, B=3
?0
et ne présentent aucune lacune.Créer un tableau statique allValues comme indiqué dans cette réponse
Ceci est également utile lorsque vous souhaitez énumérer les valeurs et fonctionne pour tous les types Enum
la source
static let count = allValues.count
. Ensuite, vous pouvez rendre leallValues
privé si vous le souhaitez.Si l'implémentation n'a rien contre l'utilisation d'
Count
énumérations entières, vous pouvez ajouter une valeur de membre supplémentaire appelée pour représenter le nombre de membres dans l'énumération - voir l'exemple ci-dessous:Vous pouvez maintenant obtenir le nombre de membres dans l'énumération en appelant,
TableViewSections.Count.rawValue
ce qui renverra 2 pour l'exemple ci-dessus.Lorsque vous gérez l'énumération dans une instruction switch, assurez-vous de lancer un échec d'assertion lorsque vous rencontrez le
Count
membre là où vous ne vous attendez pas:la source
Ce type de fonction est capable de renvoyer le décompte de votre énumération.
Swift 2 :
Swift 3 :
la source
enum
est égalementHashable
du même type.compter :
eEventTabType.allValues.count
index:
objeEventTabType.index
Prendre plaisir :)
la source
Oh hé tout le monde, qu'en est-il des tests unitaires?
Ceci combiné avec la solution d'Antonio:
dans le code principal vous donne O (1) plus vous obtenez un test qui échoue si quelqu'un ajoute un cas d'énumération
five
et ne met pas à jour l'implémentation decount
.la source
Cette fonction repose sur 2 comportements courants non documentés (Swift 1.1)
enum
:enum
n'est qu'un index decase
. Si le nombre de cas est compris entre 2 et 256, c'estUInt8
.enum
bit a été converti à partir d'un index de cas non valide , ilhashValue
est0
Alors utilisez à vos risques et périls :)
Usage:
la source
J'ai écrit une extension simple qui donne à toutes les énumérations où la valeur brute est un entier une
count
propriété:Malheureusement, il donne la
count
propriétéOptionSetType
là où cela ne fonctionnera pas correctement, voici donc une autre version qui nécessite une conformité explicite auCaseCountable
protocole pour toute énumération des cas que vous souhaitez compter:C'est très similaire à l'approche publiée par Tom Pelaia, mais fonctionne avec tous les types entiers.
la source
Bien sûr, ce n'est pas dynamique mais pour de nombreuses utilisations, vous pouvez vous en tirer avec une variable statique ajoutée à votre Enum
static var count: Int{ return 7 }
puis utilisez-le comme
EnumName.count
la source
OU
* Sur Swift 4.2 (Xcode 10) peut utiliser:
la source
Pour mon cas d'utilisation, dans une base de code où plusieurs personnes pourraient ajouter des clés à une énumération, et ces cas devraient tous être disponibles dans la propriété allKeys, il est important que allKeys soit validé par rapport aux clés de l'énumération. Ceci afin d'éviter que quelqu'un oublie d'ajouter sa clé à la liste de toutes les clés.Faire correspondre le nombre du tableau allKeys (d'abord créé comme un ensemble pour éviter les dupes) avec le nombre de clés dans l'énumération garantit qu'elles sont toutes présentes.
Certaines des réponses ci-dessus montrent la manière d'y parvenir dans Swift 2, mais aucune ne fonctionne dans Swift 3 . Voici la version formatée de Swift 3 :
En fonction de votre cas d'utilisation, vous voudrez peut-être simplement exécuter le test en développement pour éviter la surcharge liée à l'utilisation de allKeys à chaque demande
la source
Pourquoi rendez-vous tout cela si complexe? Le compteur SIMPLEST de l'énumération Int consiste à ajouter:
case Count
À la fin. Et ... alto - maintenant vous avez le décompte - rapide et simple
la source
0
et qu'il n'y ait pas de lacunes dans la séquence.Si vous ne voulez pas baser votre code dans la dernière énumération, vous pouvez créer cette fonction dans votre énumération.
la source
Une version Swift 3 fonctionnant avec
Int
les énumérations de types:Crédits: Basé sur les réponses de bzz et Nate Cook.
Generic
IntegerType
(dans Swift 3 renommé enInteger
) n'est pas pris en charge, car il s'agit d'un type générique fortement fragmenté qui manque de nombreuses fonctions.successor
n'est plus disponible avec Swift 3.Sachez que le commentaire de Code Commander à la réponse de Nate Cooks est toujours valide:
Pour autant que je sache, il n'y a actuellement aucune solution de contournement lors de l'utilisation de cette extension de protocole (et de la non-implémentation dans chaque énumération comme Nate Cook l'a fait) en raison des propriétés stockées statiques qui ne sont pas prises en charge dans les types génériques.
Quoi qu'il en soit, pour les petites énumérations, cela ne devrait pas poser de problème. Un cas d'utilisation typique serait le
section.count
pourUITableViews
comme déjà mentionné par Zorayr.la source
En étendant la réponse de Matthieu Riegler, il s'agit d'une solution pour Swift 3 qui ne nécessite pas l'utilisation de génériques, et peut être facilement appelée en utilisant le type enum avec
EnumType.elementsCount
:la source
J'ai résolu ce problème pour moi-même en créant un protocole (EnumIntArray) et une fonction utilitaire globale (enumIntArray) qui facilitent l'ajout d'une variable "All" à n'importe quelle énumération (en utilisant swift 1.2). La variable "all" contiendra un tableau de tous les éléments de l'énumération afin que vous puissiez utiliser all.count pour le nombre
Cela ne fonctionne qu'avec les énumérations qui utilisent des valeurs brutes de type Int, mais peut-être peut-il fournir une certaine inspiration pour d'autres types.
Il aborde également les problèmes de «manque de numérotation» et de «temps excessif pour itérer» que j'ai lus ci-dessus et ailleurs.
L'idée est d'ajouter le protocole EnumIntArray à votre enum, puis de définir une variable statique «all» en appelant la fonction enumIntArray et de lui fournir le premier élément (et le dernier s'il y a des lacunes dans la numérotation).
Étant donné que la variable statique n'est initialisée qu'une seule fois, la surcharge liée au passage de toutes les valeurs brutes ne touche votre programme qu'une seule fois.
exemple (sans lacunes):
exemple (avec des lacunes):
Voici le code qui l'implémente:
la source
Ou vous pouvez simplement définir l'
_count
extérieur de l'énumération et l'attacher de manière statique:De cette façon, quel que soit le nombre d'énumérations que vous créez, il ne sera créé qu'une seule fois.
(supprimez cette réponse si
static
c'est le cas)la source
La méthode suivante provient de CoreKit et est similaire aux réponses suggérées par d'autres. Cela fonctionne avec Swift 4.
Ensuite, il vous suffit d'appeler
Weekdays.allValues.count
.la source
la source
mais soyez prudent avec l'utilisation sur les types non-enum. Une solution de contournement pourrait être:
la source
Il peut utiliser une constante statique qui contient la dernière valeur de l'énumération plus un.
la source
C'est mineur, mais je pense qu'une meilleure solution O (1) serait la suivante ( UNIQUEMENT si votre énumération
Int
commence à x, etc.):La réponse actuellement sélectionnée, je crois toujours, est la meilleure réponse pour toutes les énumérations, sauf si vous travaillez avec,
Int
je recommande cette solution.la source
guard
contre laquelle sCOUNT
et renvoie une erreur, renvoie false, etc. pour résoudre votre problème de représentation des types.