enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
Por ejemplo, ¿cómo puedo hacer algo como:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
Ejemplo resultante:
♠
♥
♦
♣
Respuestas:
Swift 4.2+
Comenzando con Swift 4.2 (con Xcode 10), solo agregue conformidad de protocolo
CaseIterable
para beneficiarseallCases
. Para agregar esta conformidad de protocolo, simplemente necesita escribir en alguna parte:Si la enumeración es suya, puede especificar la conformidad directamente en la declaración:
Luego, el siguiente código imprimirá todos los valores posibles:
Compatibilidad con versiones anteriores de Swift (3.xy 4.x)
Si necesita admitir Swift 3.xo 4.0, puede imitar la implementación de Swift 4.2 agregando el siguiente código:
fuente
String
, a diferencia de la pregunta actual de desbordamiento de pila.Esta publicación es relevante aquí https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift
Esencialmente, la solución propuesta es
fuente
Enum.Values(typeof(FooEnum))
pero expuesto como un método de extensión (como map o reduce).FooEnum.values() :: values(EnumType -> [EnumType])
Hice una función de utilidad
iterateEnum()
para iterar casos paraenum
tipos arbitrarios .Aquí está el uso de ejemplo:
Qué salidas:
Pero, esto es solo para propósitos de depuración o prueba : esto se basa en varios comportamientos del compilador Swift1.1 no documentados, por lo tanto, úselo bajo su propio riesgo.
Aquí está el código:
La idea subyacente es:
enum
, excluyendoenum
s con tipos asociados, es solo un índice de casos cuando el recuento de los casos es2...256
, es idéntico aUInt8
, cuándo257...65536
, es,UInt16
etc. Por lo tanto, puede serunsafeBitcast
de tipos enteros sin signo correspondientes..hashValue
de los valores de enumeración es el mismo que el índice del caso..hashValue
de valores de enumeración bitcasted de índice inválido es0
.Revisado para Swift2 e implementado ideas de casting de la respuesta de @ Kametrixom :
Revisado para Swift3:
Revisado para Swift3.0.1:
fuente
withUnsafePointer
withMemoryRebound
y otraspointee
cosas, entonces úsala por todos los medios. De lo contrario, lo evitaría.Las otras soluciones funcionan, pero todas suponen, por ejemplo, el número de posibles rangos y trajes, o cuál puede ser el primer y el último rango. Es cierto que el diseño de una baraja de cartas probablemente no va a cambiar mucho en el futuro previsible. En general, sin embargo, es mejor escribir código que haga la menor cantidad posible de suposiciones. Mi solución:
He agregado un tipo sin formato a la
Suit
enumeración, por lo que puedo usarSuit(rawValue:)
para acceder a losSuit
casos:Debajo de la implementación del
createDeck()
método de la Tarjeta .init(rawValue:)
es un inicializador disponible y devuelve un opcional. Por desenvolver y la comprobación de su valor en los dos estados mientras, no hay necesidad de asumir el número deRank
oSuit
casos:Aquí es cómo llamar al
createDeck
método:fuente
Suit
. En este ejemplo, puede hacerlo, pero el ejercicio estaba destinado a ayudarlo a trabajar con losenums
que recibió como si fueran de una fuente externa.Tropecé con los bits y bytes y creé una extensión que luego descubrí que funciona de manera muy similar a la respuesta de @rintaro . Se usa así:
Lo notable es que se puede usar en cualquier enumeración sin valores asociados. Tenga en cuenta que esto no funciona para las enumeraciones que no tienen casos.
Al igual que con la respuesta de @rintaro , este código usa la representación subyacente de una enumeración. Esta representación no está documentada y podría cambiar en el futuro, lo que la rompería. No recomiendo el uso de esto en producción.
Código (Swift 2.2, Xcode 7.3.1, no funciona en Xcode 10):
Código (Swift 3, Xcode 8.1, no funciona en Xcode 10):
No tengo idea de por qué lo necesito
typealias
, pero el compilador se queja sin él.fuente
withUnsafePointer
...pointee}
porwithUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } }
Puede iterar a través de una enumeración mediante la implementación del
ForwardIndexType
protocolo.El
ForwardIndexType
protocolo requiere que defina unasuccessor()
función para recorrer los elementos.Iterar sobre un rango abierto o cerrado (
..<
o...
) llamará internamente a lasuccessor()
función que le permite escribir esto:fuente
successor()
método correctamente definido (primera opción) eliminaría la necesidad deenum
tener un tipo asociado. +1Este problema ahora es mucho más fácil. Aquí está mi solución Swift 4.2:
Pre 4.2:
Me gusta esta solución que armé después de encontrar " Comprensión de listas en Swift ".
Utiliza Int raws en lugar de Strings pero evita escribir dos veces, permite personalizar los rangos y no codifica los valores brutos.
Esta es una versión Swift 4 de mi solución original, pero vea la mejora 4.2 anterior:
fuente
En principio, es posible hacerlo de esta manera, suponiendo que no utilice la asignación de valores sin procesar para los casos de enum:
fuente
enum ItWontWorkForThisEnum {case a, b, c}
Si le da a la enumeración un valor Int sin procesar , hará que el bucle sea mucho más fácil.
Por ejemplo, puede usar
anyGenerator
para obtener un generador que pueda enumerar sus valores:Sin embargo, esto parece un patrón bastante común, ¿no sería bueno si pudiéramos hacer enumerable cualquier tipo de enumeración simplemente cumpliendo con un protocolo? Bueno, con Swift 2.0 y extensiones de protocolo, ¡ahora podemos!
Simplemente agregue esto a su proyecto:
Ahora, cada vez que cree una enumeración (siempre que tenga un valor bruto Int), puede hacerla enumerable conforme al protocolo:
Si sus valores de enumeración no comienzan con
0
(el valor predeterminado), anule elfirstRawValue
método:La clase final de Traje, que incluye el reemplazo
simpleDescription
con el protocolo CustomStringConvertible más estándar , se verá así:Sintaxis de Swift 3:
fuente
Actualizado a Swift 2.2 +
Es el código actualizado a la respuesta de Swift 2.2 form @ Kametrixom
Para Swift 3.0+ (muchas gracias a @Philip )
fuente
Solución Swift 5:
fuente
Me encontré haciendo
.allValues
mucho en todo mi código. Finalmente descubrí una manera de simplemente conformarme a unIteratable
protocolo y tener unrawValues()
método.fuente
Xcode 10 con Swift 4.2
Llámalo
Huellas dactilares:
versiones anteriores
Por
enum
representarInt
Llámalo así:
Huellas dactilares:
Por
enum
representarString
Llámalo
Huellas dactilares:
fuente
EDITAR: Propuesta de Evolución Rápida SE-0194 La Colección Derivada de Casos Enum propone una solución nivelada para este problema. Lo vemos en Swift 4.2 y versiones posteriores. La propuesta también señala algunas soluciones alternativas que son similares a algunas ya mencionadas aquí, pero podría ser interesante ver de todos modos.
También mantendré mi publicación original por completo.
Este es otro enfoque basado en la respuesta de @ Peymmankh, adaptado a Swift 3 .
fuente
¿Qué tal esto?
fuente
Puedes intentar enumerar así
fuente
static var enumerate = [Mercury, Venus, Earth, Mars]
, por lo que es una respuesta deficiente en comparación con la respuesta más votada stackoverflow.com/a/24137319/1033581return [Mercury, Venus, Mars]
lugar dereturn [Mercury, Venus, Earth, Mars]
return [.spades, .hearts, .clubs]
el compilador no dirá nada y luego, cuando intente usarlo en código, obtendrá[TestApp.Suit.spades, TestApp.Suit.hearts, TestApp.Suit.clubs]
, ese fue mi punto, que si está tratando con un gran enumeración y tiene que agregar o eliminar casos de vez en cuando, su solución es propensa a errores de omisión, mientras que la respuesta actual, aunque no es concisa, es más segura.En Swift 3, cuando tiene la enumeración subyacente
rawValue
, puede implementar elStrideable
protocolo. Las ventajas son que no se crean matrices de valores como en algunas otras sugerencias y que el bucle Swift estándar "for in" funciona, lo que hace una buena sintaxis.fuente
Esta solución logra el equilibrio adecuado entre legibilidad y mantenibilidad.
fuente
Lo siento, mi respuesta fue específica de cómo usé esta publicación en lo que tenía que hacer. Para aquellos que se topan con esta pregunta y buscan una forma de encontrar un caso dentro de una enumeración, esta es la forma de hacerlo (novedad en Swift 2):
Editar: minúsculas camelCase ahora es el estándar para los valores de enumeración de Swift 3
Para aquellos que se preguntan sobre la enumeración en una enumeración, las respuestas dadas en esta página que incluyen un var / let estático que contiene una matriz de todos los valores de enumeración son correctas. El último código de ejemplo de Apple para tvOS contiene exactamente la misma técnica.
Dicho esto, deberían construir un mecanismo más conveniente en el lenguaje (Apple, ¿estás escuchando?).
fuente
El experimento fue: EXPERIMENTO
Agregue un método a la Tarjeta que cree una baraja completa de cartas, con una carta de cada combinación de rango y palo.
Entonces, sin modificar o mejorar el código dado que no sea agregar el método (y sin usar cosas que aún no se han enseñado), se me ocurrió esta solución:
fuente
Aquí hay un método que uso para iterar
enum
y proporcionar múltiples tipos de valores desde unoenum
Esta es la salida:
El número cero en francés: zéro, español: cero, japonés: nuru
El número uno en francés: un, español: uno, japonés: ichi
El número dos en francés: deux, español: dos, japonés: ni
El número tres en francés : trois, español: tres, japonés: san
El número cuatro en francés: quatre, español: cuatro, japonés: shi
El número cinco en francés: cinq, español: cinco, japonés: ir
El número seis en francés: seis, español: seis, japonés: roku
El número siete en francés: sept, español: siete, japonés: shichi
Total de 8 casos
siete en japonés: shichi
ACTUALIZAR
Recientemente creé un protocolo para manejar la enumeración. El protocolo requiere una enumeración con un valor bruto Int:
fuente
Esto parece un truco, pero si usa valores sin procesar, puede hacer algo como esto
fuente
Al tratar
Swift 2.0
aquí es mi sugerencia:He agregado el tipo sin formato a
Suit
enum
entonces:
fuente
Al igual que con la respuesta de @Kametrixom aquí , creo que devolver una matriz sería mejor que devolver AnySequence, ya que puede tener acceso a todas las ventajas de Array, como count, etc.
Aquí está la reescritura:
fuente
Otra solución:
fuente
Esta es una publicación bastante antigua, de Swift 2.0. Ahora hay algunas soluciones mejores aquí que usan las funciones más nuevas de swift 3.0: iterar a través de una enumeración en Swift 3.0
Y en esta pregunta hay una solución que utiliza una nueva característica de Swift 4.2 (aún no publicado cuando escribo esta edición): ¿Cómo obtengo el recuento de una enumeración Swift?
Hay muchas buenas soluciones en este hilo y otras, sin embargo, algunas de ellas son muy complicadas. Me gusta simplificar lo más posible. Aquí hay una solución que puede o no funcionar para diferentes necesidades, pero creo que funciona bien en la mayoría de los casos:
Para iterar:
fuente
Las enumeraciones tienen
toRaw()
yfromRaw()
métodos. Entonces, si su valor bruto es unInt
, puede iterar del primero al últimoenum
:Un problema es que debe probar los valores opcionales antes de ejecutar el
simpleDescription
método, por loconvertedSuit
que primero establecemos nuestro valor y luego establecemos una constante enconvertedSuit.simpleDescription()
fuente
Aquí está mi enfoque sugerido. No es completamente satisfactorio (¡soy muy nuevo en Swift y OOP!), Pero tal vez alguien pueda refinarlo. La idea es que cada enumeración proporcione su propia información de rango
.first
y.last
propiedades. Agrega solo dos líneas de código a cada enumeración: todavía está un poco codificado, pero al menos no está duplicando todo el conjunto. Requiere modificar laSuit
enumeración para que sea un Int como laRank
enumeración es, en lugar de sin tipo.En lugar de hacer eco de toda la solución, aquí está el código que agregué a la
.
enumeración, en algún lugar después de las declaraciones de casos (laSuit
enumeración es similar):y el bucle que usé para construir el mazo como una matriz de String. (La definición del problema no indicaba cómo se iba a estructurar el mazo).
No es satisfactorio porque las propiedades están asociadas a un elemento en lugar de a la enumeración. Pero sí agrega claridad a los bucles 'for'. Me gustaría decirlo en
Rank.first
lugar deRank.Ace.first
. Funciona (con cualquier elemento), pero es feo. ¿Alguien puede mostrar cómo elevar eso al nivel de enumeración?Y para que funcione, saqué el
createDeck
método de la estructura de la Tarjeta. No pude averiguar cómo obtener una matriz [String] devuelta desde esa estructura, y de todos modos parece un mal lugar para poner un método de este tipo.fuente
Lo hice usando la propiedad calculada, que devuelve la matriz de todos los valores (gracias a esta publicación http://natecook.com/blog/2014/10/loopy-random-enum-ideas/ ). Sin embargo, también usa int raw-values, pero no necesito repetir todos los miembros de la enumeración en una propiedad separada.
ACTUALIZACIÓN Xcode 6.1 cambió un poco la forma de obtener el uso de un miembro enum
rawValue
, así que arreglé el listado. También se corrigió un pequeño error con un error primerorawValue
.fuente
Basado en la respuesta de Rick: esto es 5 veces más rápido
fuente
Count
caso romperáswitch
implementaciones exhaustivas yCaseIterable
conformidad.