¿Cómo puedo determinar el número de casos en una enumeración Swift?
(Me gustaría evitar enumerar manualmente todos los valores , o usar el viejo " truco enum_count " si es posible).
¿Cómo puedo determinar el número de casos en una enumeración Swift?
(Me gustaría evitar enumerar manualmente todos los valores , o usar el viejo " truco enum_count " si es posible).
A partir de Swift 4.2 (Xcode 10) puede declarar conformidad con el CaseIterable
protocolo, esto funciona para todas las enumeraciones sin valores asociados:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
El número de casos ahora se obtiene simplemente con
print(Stuff.allCases.count) // 4
Para más información, ver
Tengo una publicación de blog que entra en más detalles sobre esto, pero siempre que el tipo sin formato de su enumeración sea un entero, puede agregar un recuento de esta manera:
fuente
case A=1, B=3
?enum
tener unInt
valor bruto que olvidó mencionar: las enumeraciones rápidas con valores brutos Int no tienen que comenzar desde 0 (aunque ese es el comportamiento predeterminado) y sus valores brutos pueden ser arbitrarios, no tienen incrementar en 1 (aunque ese es el comportamiento predeterminado).Actualización de Xcode 10
Adopte el
CaseIterable
protocolo en la enumeración, proporciona unaallCases
propiedad estática que contiene todos los casos de enumeración como aCollection
. Simplemente use sucount
propiedad para saber cuántos casos tiene la enumeración.Vea la respuesta de Martin como ejemplo (y vote sus respuestas en lugar de las mías)
Advertencia : el siguiente método ya no parece funcionar.
No conozco ningún método genérico para contar el número de casos enum. Sin embargo, he notado que la
hashValue
propiedad de los casos enum es incremental, comenzando desde cero y con el orden determinado por el orden en que se declaran los casos. Entonces, el hash de la última enumeración más uno corresponde al número de casos.Por ejemplo con esta enumeración:
count
devuelve 4.No puedo decir si eso es una regla o si alguna vez cambiará en el futuro, así que úselo bajo su propio riesgo :)
fuente
hashValues
estas cosas; todo lo que sabemos es que es un valor único aleatorio: podría cambiar muy fácilmente en el futuro dependiendo de algún detalle de implementación del compilador; pero en general, la falta de funcionalidad de conteo incorporada es inquietante.case ONE = 0
, puede reemplazarhashValue
conrawValue
.static var count = 4
lugar de dejar su destino en el destino de futuras implementaciones de SwiftDefino un protocolo reutilizable que realiza automáticamente el recuento de casos según el enfoque publicado por Nate Cook.
Entonces puedo reutilizar este protocolo, por ejemplo, de la siguiente manera:
fuente
count++
decount+=1
puesto++
de notación se eliminará en Swift 3static var caseCount: Int { get }
? ¿Por qué la necesidad de lastatic func
?case A=1, B=3
?0
y no tengan brechas.Cree una matriz estática de todos los valores como se muestra en esta respuesta
Esto también es útil cuando desea enumerar los valores, y funciona para todos los tipos de Enum
fuente
static let count = allValues.count
. Entonces puedes hacer elallValues
privado si lo deseas.Si la implementación no tiene nada en contra del uso de enumeraciones enteras, puede agregar un valor de miembro adicional llamado
Count
para representar el número de miembros en la enumeración; consulte el siguiente ejemplo:Ahora puede obtener el número de miembros en la enumeración llamando,
TableViewSections.Count.rawValue
lo que devolverá 2 para el ejemplo anterior.Cuando maneja la enumeración en una declaración de cambio, asegúrese de lanzar un error de aserción cuando encuentre al
Count
miembro donde no lo espera:fuente
Este tipo de función puede devolver el recuento de su enumeración.
Swift 2 :
Swift 3 :
fuente
enum
es del mismo tipo.Hashable
cuenta:
eEventTabType.allValues.count
índice:
objeEventTabType.index
Disfruta :)
fuente
Oh, hola a todos, ¿qué pasa con las pruebas unitarias?
Esto combinado con la solución de Antonio:
en el código principal le da O (1) además de obtener una prueba fallida si alguien agrega un caso de enumeración
five
y no actualiza la implementación decount
.fuente
Esta función se basa en 2 comportamientos de corriente no documentada (Swift 1.1)
enum
:enum
es solo un índice decase
. Si el recuento de casos es de 2 a 256, esUInt8
.enum
bit fue lanzado desde un índice de caso inválido ,hashValue
es0
Así que úselo bajo su propio riesgo :)
Uso:
fuente
Escribí una extensión simple que proporciona todas las enumeraciones donde el valor bruto es una
count
propiedad entera :Desafortunadamente, le da a la
count
propiedadOptionSetType
donde no funcionará correctamente, por lo que aquí hay otra versión que requiere conformidad explícita con elCaseCountable
protocolo para cualquier enumeración de los casos que desea contar:Es muy similar al enfoque publicado por Tom Pelaia, pero funciona con todos los tipos enteros.
fuente
Por supuesto, no es dinámico, pero para muchos usos puede obtener una var estática agregada a su Enum
static var count: Int{ return 7 }
y luego úsalo como
EnumName.count
fuente
O
* En Swift 4.2 (Xcode 10) puede usar:
fuente
Para mi caso de uso, en una base de código donde varias personas podrían estar agregando claves a una enumeración, y estos casos deberían estar disponibles en la propiedad allKeys, es importante que todas las claves sean validadas contra las claves de la enumeración. Esto es para evitar que alguien se olvide de agregar su clave a la lista de todas las claves. Hacer coincidir el recuento de la matriz allKeys (creada primero como un conjunto para evitar engaños) con el número de claves en la enumeración asegura que todos estén presentes.
Algunas de las respuestas anteriores muestran la forma de lograr esto en Swift 2, pero ninguna funciona en Swift 3 . Aquí está la versión formateada de Swift 3 :
Dependiendo de su caso de uso, es posible que desee ejecutar la prueba en desarrollo para evitar la sobrecarga de usar allKeys en cada solicitud
fuente
¿Por qué lo haces todo tan complejo? El contador SIMPLEST de Int enum es agregar:
case Count
En el final. Y ... viola - ahora tienes la cuenta - rápido y simple
fuente
0
y no tengan espacios en la secuencia.Si no desea basar su código en la última enumeración, puede crear esta función dentro de su enumeración.
fuente
Una versión de Swift 3 que funciona con
Int
enumeraciones de tipo:Créditos: Basado en las respuestas de bzz y Nate Cook.
Genérico
IntegerType
(en Swift 3 renombrado aInteger
) no es compatible, ya que es un tipo genérico muy fragmentado que carece de muchas funciones.successor
ya no está disponible con Swift 3.Tenga en cuenta que el comentario de Code Commander a la respuesta de Nate Cooks sigue siendo válido:
Hasta donde sé, actualmente no hay una solución alternativa cuando se usa esto como extensión de protocolo (y no se implementa en cada enumeración como lo hizo Nate Cook) debido a que las propiedades almacenadas estáticas no son compatibles con los tipos genéricos.
De todos modos, para enumeraciones pequeñas esto no debería ser un problema. Un caso de uso típico sería el
section.count
deUITableViews
como ya se ha mencionado por Zorayr.fuente
Ampliando la respuesta de Matthieu Riegler, esta es una solución para Swift 3 que no requiere el uso de genéricos, y se puede llamar fácilmente usando el tipo enum con
EnumType.elementsCount
:fuente
Resolví este problema por mí mismo creando un protocolo (EnumIntArray) y una función de utilidad global (enumIntArray) que hace que sea muy fácil agregar una variable "All" a cualquier enumeración (usando swift 1.2). La variable "all" contendrá una matriz de todos los elementos en la enumeración para que pueda usar all.count para el conteo
Solo funciona con enumeraciones que usan valores sin procesar del tipo Int, pero quizás puede proporcionar alguna inspiración para otros tipos.
También aborda los problemas de "brecha en la numeración" y "tiempo excesivo para repetir" que he leído anteriormente y en otros lugares.
La idea es agregar el protocolo EnumIntArray a su enumeración y luego definir una variable estática "all" llamando a la función enumIntArray y proporcionarle el primer elemento (y el último si hay espacios en la numeración).
Debido a que la variable estática solo se inicializa una vez, la sobrecarga de pasar por todos los valores sin procesar solo afecta a su programa una vez.
ejemplo (sin espacios):
ejemplo (con huecos):
Aquí está el código que lo implementa:
fuente
O simplemente puede definir el
_count
exterior de la enumeración y adjuntarlo estáticamente:De esa manera, no importa cuántas enumeraciones cree, solo se creará una vez.
(elimine esta respuesta si
static
hace eso)fuente
El siguiente método proviene de CoreKit y es similar a las respuestas que otros han sugerido. Esto funciona con Swift 4.
Entonces solo necesitas llamar
Weekdays.allValues.count
.fuente
fuente
pero tenga cuidado con el uso en tipos que no sean enum. Algunas soluciones podrían ser:
fuente
Puede usar una constante estática que contiene el último valor de la enumeración más uno.
fuente
Esto es menor, pero creo que una mejor solución O (1) sería la siguiente ( SOLO si su enumeración
Int
comienza en x, etc.):La respuesta seleccionada actual que todavía creo que es la mejor respuesta para todas las enumeraciones, a menos que esté trabajando
Int
, le recomiendo esta solución.fuente
guard
está en contraCOUNT
y arroja un error, devuelve falso, etc. para resolver su preocupación por la representación de tipos.