Swift: ¿Convertir el valor de enumeración en String?

141

Dada la siguiente enumeración:

enum Audience {
    case Public
    case Friends
    case Private
}

¿Cómo obtengo la cadena "Public"de la audienceconstante a continuación?

let audience = Audience.Public
ma11hew28
fuente
2
compruebe esta respuesta, puede darle algunas ideas sobre cómo puede lograrlo: stackoverflow.com/questions/24648726/enums-with-data-in-swift/…
holex
en Swift 2 y xcode7 no necesita cambiar nada a su código, solo useprint("\(audience)")
gbdavid
77
Odio que el ecosistema Swift ahora esté lleno de respuestas muy anticuadas como esta. A partir de XCode8.2 / Swift3, es tan fácil comoString(describing: yourEnumValue)
Travis Griggs el
@TravisGriggs Ya no funciona para Xcode 11.4
DawnSong

Respuestas:

156

No estoy seguro de en qué versión de Swift se agregó esta característica, pero en este momento ( Swift 2.1 ) solo necesita este código:

enum Audience : String {
    case public
    case friends
    case private
}

let audience = Audience.public.rawValue // "public"

Cuando se utilizan cadenas para valores sin formato , el valor implícito para cada caso es el texto del nombre de ese caso .

[...]

enum CompassPoint : String {
    case north, south, east, west
}

En el ejemplo anterior, CompassPoint.south tiene un valor bruto implícito de "sur", y así sucesivamente.

Accede al valor sin formato de un caso de enumeración con su propiedad rawValue:

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"

Fuente.

DevAndArtist
fuente
8
en xcode7.3 swift2.2, si hago cosas como: print("appState: \(application.applicationState)") obtengo appState: UIApplicationState cuál es el tipo y no la representación de cadena real del valor de enumeración. ¿Me estoy perdiendo de algo? (PD: para rawValue solo obtengo el valor Int ...)
Martin
@Cyrus su escenario es diferente de lo que se preguntó en este hilo. .rawValuedevolverá el valor bruto de su enumeración. La tuya es la public enum UIApplicationState : Intque de hecho es de tipo Int. Tampoco has leído mi respuesta, que tiene una cita de los documentos de Apple. ... Si todavía desea convertir UIApplicationStatea cadena, le sugiero que amplíe UIApplicationStatecon una propiedad computada personalizadaextension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }
DevAndArtist
No resuelve el problema con tener enumeraciones de tipo no String
denis631
1
@ denis631 ¿qué quieres decir? El tipo crudo de una enumeración puede ser cualquier cosa. Una enumeración puede incluso conformarse OptionSetsi realmente lo desea. Y la pregunta original es sobre Strings de todos modos.
DevAndArtist
1
si mi enumeración se escribe así, prueba enumeración: Int {case A, B}, el rawValue por supuesto devolverá int, lo que estamos buscando es una forma de obtener el nombre del caso como String. Esto es exactamente lo que hizo @DanilShaykhutdinov. Mire su respuesta y en la pregunta original, la enumeración no tiene ningún tipo, ni una Cadena o Int.
denis631
209

La interfaz idiomática para 'obtener una cadena' es usar la CustomStringConvertible interfaz y acceder al descriptiongetter. Define tu enumcomo:

enum Foo : CustomStringConvertible {
  case Bing
  case Bang
  case Boom
  
  var description : String { 
    switch self {
    // Use Internationalization, as appropriate.
    case .Bing: return "Bing"
    case .Bang: return "Bang"
    case .Boom: return "Boom"
    }
  }
}

En acción:

 > let foo = Foo.Bing
foo: Foo = Bing
 > println ("String for 'foo' is \(foo)"
String for 'foo' is Bing

Actualizado : para Swift> = 2.0, reemplazado PrintableporCustomStringConvertible

Nota : El uso CustomStringConvertiblepermite Fooadoptar un tipo sin procesar diferente. Por ejemplo enum Foo : Int, CustomStringConvertible { ... }es posible. Esta libertad puede ser útil.

GoZoner
fuente
2
Otra forma más corta de crear la cadena println es: "La cadena para 'foo' es (foo)"
John MP Knox
3
@ JohnM.P.Knox no olvide la barra diagonal inversa como en "Cadena para 'foo' es \ (foo)". Editar OK, es el editor el que se está deshaciendo de él, tuve que ingresar 2 de ellos para que se muestre
envíe
¿De qué sirve CustomStringConvertiblesi esto funciona igual de bien sin él?
Daniel van der Merwe
3
CustomStringConvertiblepermite / requiere que defina descriptioncuál le permite decidir qué cadena usar para cada caso de enumeración; esto es importante para la internacionalización seguramente y tal vez la legibilidad del código. Si no te importan, entonces puedes usar 'enum Foo: String {/ * ... * /} `
GoZoner
2
Esta es la respuesta correcta si su enumeración no es una Cadena o si desea una cadena diferente a la de RawValue. @ denis631
Haagenti
32

Por ahora, redefiniré la enumeración como:

enum Audience: String {
    case Public = "Public"
    case Friends = "Friends"
    case Private = "Private"
}

para que yo pueda hacer:

audience.toRaw() // "Public"

Pero, ¿no es redundante esta nueva definición de enumeración? ¿Puedo mantener la definición de enumeración inicial y hacer algo como:

audience.toString() // "Public"
ma11hew28
fuente
3
A partir de Xcode 7 Beta 3, puede escribir su respuesta, pero sin el = Stringporque obtiene automáticamente un valor sin formato (nombre del caso) si no proporciona ninguno.
Qbyte
3
En lugar de .toString () ahora use .rawValue
SoftDesigner el
En Swift 1.2 puedes usar: println (Audience.Friends.rawValue)
Oleg Popov
32

En Swift 3, puedes usar esto

var enumValue = Customer.Physics
var str = String(describing: enumValue)

de Swift cómo usar la enumeración para obtener el valor de cadena

Danil Shaykhutdinov
fuente
2
Esto es realmente útil, especialmente si mi enumno se basa en Strings
daspianist
1
"\(enumValue)"Hace lo mismo. ^^
eonista
Esta es una mejor respuesta. No requiere hacer su tipo de cadena de enumeración.
scord
24

Me gusta usar Printablecon Raw Values.

enum Audience: String, Printable {
    case Public = "Public"
    case Friends = "Friends"
    case Private = "Private"

    var description: String {
        return self.rawValue
    }
}

Entonces podemos hacer:

let audience = Audience.Public.description // audience = "Public"

o

println("The value of Public is \(Audience.Public)") 
// Prints "The value of Public is Public"
Simple99
fuente
1
Me gusta más que la respuesta seleccionada porque puedo hacerloAudience(rawValue: "Friends")
tidwall
12

Actualizado para el lanzamiento de Xcode 7 GM. Funciona como uno esperaría ahora, ¡gracias Apple!

enum Rank:Int {
    case Ace = 1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}

let r = Rank.Ace

print(r)               // prints "Ace"
print("Rank: \(r)!")   // prints "Rank: Ace!"
par
fuente
2
En Swift 2.0, ajustarse a en CustomStringConvertiblerealidad permitiría usar solo print(r)en este caso.
matm
En Xcode 7 beta 4, reflect () parece haber sido deshabilitado a favor de Mirror (reflecting: x). Sin embargo, el objeto devuelto tiene una estructura diferente.
GSnyder
1
Actualizar la respuesta por favor
Ben Sinclair
10

No podría ser más simple que esto en Swift 2 y el último Xcode 7 (no es necesario especificar el tipo de enumeración, o .rawValue, descriptores, etc.)

Actualizado para Swift 3 y Xcode 8:

    enum Audience {
        case Public
        case Friends
        case Private
    }

    let audience: Audience = .Public  // or, let audience = Audience.Public
    print(audience) // "Public"
gbdavid
fuente
Funcionó perfectamente con mis enumeraciones respaldadas por Int
chrislarson
Solo una observación: esto funciona para enumeraciones de creación propia, pero no funciona para algo como HKWorkoutActivityType
Ace Green
Así como para cadenas localizadas;)
Eugene Braginets
2
La pregunta original era sobre cómo convertir el valor de enumeración en una cadena en sus propias enumeraciones, así que para eso respondí ... Si desea manejar las enumeraciones UIKit / AppKit, por supuesto, es una historia diferente.
gbdavid
1
@gbdavid - ¿Hay una Q para las UIKit / AppKit Enums? Busqué en Google y no pude encontrarlo. Puedo enviar Q si es necesario.
benc
8

Un ejemplo rápido 3 y superior si se usa Ints en Enum

public enum ECategory : Int{
        case Attraction=0, FP, Food, Restroom, Popcorn, Shop, Service, None;
        var description: String {
            return String(describing: self)
        }
    }

let category = ECategory.Attraction
let categoryName = category.description //string Attraction
tsukimi
fuente
Una solución elegante. "\ (categoría)" o directamente String (que describe: categoría) también funcionaría. Incluso para enumeraciones int.
t1ser
8

Para cualquiera que lea el ejemplo en el capítulo "A Swift Tour" de "The Swift Programming Language" y busque una forma de simplificar el método simpleDescription (), al convertir la enumeración a String, lo String(self)hará:

enum Rank: Int
{
    case Ace = 1 //required otherwise Ace will be 0
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
            case .Ace, .Jack, .Queen, .King:
                return String(self).lowercaseString
            default:
                return String(self.rawValue)
        }
     }
 }
Vivek Gani
fuente
2
Solo asegúrese de no estar usando la enumeración con "@objc". Eso hace que este enfoque falle.
Matt Bearson el
5

Después de probar algunas formas diferentes, descubrí que si no quieres usar:

let audience = Audience.Public.toRaw()

Todavía puedes archivarlo usando una estructura

struct Audience {
   static let Public  = "Public"
   static let Friends = "Friends"
   static let Private = "Private"
}

entonces tu código:

let audience = Audience.Public

Funcionará como se esperaba. No es bonito y hay algunas desventajas porque no estás usando una "enumeración", no puedes usar el acceso directo solo agregando .Private ni funcionará con los casos de cambio.

Adriano Spadoni
fuente
Se ve bien. Me pregunto cuál sería la mejor práctica para este caso en particular. Preferiría usar la sintaxis de struct debido a la simplicidad, pero usar struct en lugar de enum no parece correcto, ¿o tal vez soy solo yo? Bueno, nada te impide declarar variables constantes en cualquier otro lugar, esta vez solo lo agregas dentro de una estructura para que esté organizado. Pensamientos?
schystz
Exactamente, funciona como variables constantes pero más organizadas. Como dije antes, el único problema es el "caso de cambio" y los accesos directos ". Privado". Si está creando desde cero su aplicación, intente usar "enum", use estructuras solo si el "enum" no satisface su código por alguna razón. Personalmente, evito las variables constantes y siempre uso estructuras en su lugar.
Adriano Spadoni
Lo uso para las teclas predeterminadas. En lugar de recordar las claves predeterminadas dentro de una aplicación, vuelco las claves en una estructura y las extraigo de allí.
Adrian
3

Hay varias formas de hacer esto. Puede definir una función en la enumeración que devuelve la cadena en función del valor del tipo de enumeración:

enum Audience{
    ...
func toString()->String{
  var a:String

  switch self{
   case .Public:
    a="Public"
   case .Friends:
    a="Friends"
   ...
 }
 return a
}

O puedes probar esto:

enum Audience:String{
   case Public="Public"
   case Friends="Friends"
   case Private="Private"
}

Y para usarlo:

var a:Audience=Audience.Public
println(a.toRaw())
Dhruv Ramani
fuente
1

A partir de Swift 3.0 puedes

var str = String(describing: Audience.friends)
ios mentalista
fuente
1
Increíble, pero eso funciona perfectamente. Mucho más corto que el enfoque "idiomático". ¡Gracias!
Roman