Swift: converti il ​​valore enum in String?


141

Dato il seguente enum:

enum Audience {
    case Public
    case Friends
    case Private
}

Come ottengo la stringa "Public"dalla audiencecostante sotto?

let audience = Audience.Public

2
si prega di controllare questa risposta, può darvi alcune idee su come si può raggiungere tale cosa: stackoverflow.com/questions/24648726/enums-with-data-in-swift/...
Holex

in Swift 2 e xcode7 non è necessario modificare nulla al codice, basta usareprint("\(audience)")
gbdavid

7
Odio che l'ecoscape di Swift sia ora piena di risposte molto datate come questa. A partire da XCode8.2 / Swift3, è facile comeString(describing: yourEnumValue)
Travis Griggs

@TravisGriggs Non funziona più per Xcode 11.4
DawnSong

Risposte:


156

Non sei sicuro di quale versione di Swift sia stata aggiunta questa funzionalità, ma al momento ( Swift 2.1 ) hai solo bisogno di questo codice:

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

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

Quando le stringhe vengono utilizzate per valori non elaborati, il valore implicito per ciascun caso è il testo del nome di quel caso .

[...]

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

Nell'esempio sopra, CompassPoint.south ha un valore grezzo implicito di "sud" e così via.

Si accede al valore non elaborato di un caso di enumerazione con la sua proprietà rawValue:

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

Fonte.


8
in xcode7.3 swift2.2, se faccio cose del genere: print("appState: \(application.applicationState)") ottengo appState: UIApplicationState quale sia il tipo e non la rappresentazione di stringa effettiva del valore enum. Mi sto perdendo qualcosa qui? (PS: per rawValue ottengo solo il valore Int ...)
Martin

@Cyrus il tuo scenario è diverso da quello che è stato chiesto in questo thread. .rawValuerestituirà il valore grezzo del tuo enum. Il tuo è public enum UIApplicationState : Intdavvero di tipo Int. Inoltre non hai mai letto la mia risposta che ha un preventivo dai documenti di Apple. ... Se vuoi ancora convertire UIApplicationStatein stringa ti suggerirei di estenderlo UIApplicationStatecon una proprietà calcolata personalizzataextension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }
DevAndArtist

Non risolve il problema con enumerazioni non di tipo String
denis631

1
@ denis631 che vuoi dire? Il tipo grezzo di un enum può essere qualsiasi cosa. Un enum può persino conformarsi OptionSetse lo vuoi davvero. E la domanda originale riguarda comunque le stringhe.
DevAndArtist

1
se il mio enum è scritto in questo modo, enum Test: Int {case A, B}, il rawValue ritornerà ovviamente int indietro, quello che stiamo cercando è un modo per ottenere il nome del caso come String. Questo è esattamente ciò che ha fatto @DanilShaykhutdinov. Guarda la sua risposta e nella domanda originale l'enum non ha tipo, non una stringa o int.
denis631,

209

L'interfaccia idiomatica per "ottenere una stringa" è usare l' CustomStringConvertible interfaccia e accedere al descriptiongetter. Definisci il tuo enumcome:

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"
    }
  }
}

In azione:

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

Aggiornato : per Swift> = 2.0, sostituito PrintableconCustomStringConvertible

Nota : l'utilizzo CustomStringConvertibleconsente Foodi adottare un diverso tipo di raw. Ad esempio enum Foo : Int, CustomStringConvertible { ... }è possibile. Questa libertà può essere utile.


2
Un altro modo più breve per creare la stringa println è: "La stringa per 'foo' è (foo)"
John MP Knox

3
@ JohnM.P.Knox non dimenticare la barra rovesciata come in "String for 'foo' is \ (foo)". Modifica OK, è l'editor che si sta sbarazzando di esso, ho dovuto inserirne 2 per poterlo mostrare
zmit

A cosa CustomStringConvertibleserve se funziona altrettanto bene senza di essa?
Daniel van der Merwe,

3
CustomStringConvertibleti permette / richiede di definire descriptionquale ti permette di decidere quale stringa usare per ogni caso enum - questo è importante per l'internazionalizzazione sicuramente e forse la leggibilità del codice. Se non ti interessa, puoi usare 'enum Foo: String {/ * ... * /} `
GoZoner,

2
Questa è la risposta corretta se il tuo enum non è una stringa o vuoi una stringa diversa da rawValue. @ denis631
Haagenti,

32

Per ora, ridefinirò l'enum come:

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

in modo che io possa fare:

audience.toRaw() // "Public"

Ma questa nuova definizione di enum non è ridondante? Posso mantenere la definizione di enum iniziale e fare qualcosa del tipo:

audience.toString() // "Public"

3
A partire da Xcode 7 Beta 3 puoi semplicemente scrivere la tua risposta ma senza il = Stringperché ottiene automaticamente un valore grezzo (nome del caso) se non ne fornisci uno.
Qbyte,

3
Invece di .toString () ora usa .rawValue
SoftDesigner il

In Swift 1.2 puoi usare: println (Audience.Friends.rawValue)
Oleg Popov


24

Mi piace usare Printablecon Raw Values.

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

    var description: String {
        return self.rawValue
    }
}

Quindi possiamo fare:

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

o

println("The value of Public is \(Audience.Public)") 
// Prints "The value of Public is Public"

1
Mi piace così meglio della risposta selezionata perché posso farloAudience(rawValue: "Friends")
tidwall

12

Aggiornato per il rilascio di Xcode 7 GM. Funziona come uno spererebbe ora - grazie 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!"

2
In Swift 2.0, la conformità a CustomStringConvertibleconsentirebbe effettivamente l'utilizzo proprio print(r)in questo caso.
matm

In Xcode 7 beta 4, reflection () sembra essere stato disabilitato a favore di Mirror (riflettendo: x). Tuttavia, l'oggetto restituito ha una struttura diversa.
GSnyder,

1
Aggiorna la risposta per favore
Ben Sinclair,

10

Non potrebbe essere più semplice di così in Swift 2 e nell'ultimo Xcode 7 (non è necessario specificare il tipo enum o .rawValue, i descrittori ecc ...)

Aggiornato per Swift 3 e Xcode 8:

    enum Audience {
        case Public
        case Friends
        case Private
    }

    let audience: Audience = .Public  // or, let audience = Audience.Public
    print(audience) // "Public"

Ha funzionato perfettamente con i miei enum sostenuti da Int
chrislarson,

Solo un'osservazione: questo funziona per enumerazioni create da sé, ma non per qualcosa come HKWorkoutActivityType
Ace Green

Così come per stringhe localizzate;)
Eugene Braginets il

2
La domanda originale era sulla conversione del valore enum in stringa nei tuoi enum, quindi è per questo che ho dato una risposta ... Se ti piacerebbe gestire UIKit / AppKit Enums, ovviamente è una storia diversa.
gbdavid,

1
@gbdavid - Esiste una Q per UIKit / AppKit Enums? Ho cercato su Google e non sono riuscito a trovarlo. Posso inviare Q se è necessario.
benc,

8

Un rapido esempio 3 e superiore se si utilizza Ints in 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

Una soluzione elegante "\ (categoria)" o direttamente String (che descrive: categoria) funzionerebbe anche. Anche per gli appassionati di int.
t1ser

8

Per chiunque legga l'esempio nel capitolo "A Swift Tour" di "Il linguaggio di programmazione Swift" e cerchi un modo per semplificare il metodo simpleDescription (), facendo l'enum stesso in String facendo String(self)lo farà:

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)
        }
     }
 }

2
Assicurati di non usare l'enum con "@objc". Questo fa fallire questo approccio.
Matt Bearson,

5

Dopo aver provato diversi modi, ho scoperto che se non si desidera utilizzare:

let audience = Audience.Public.toRaw()

Puoi ancora archiviarlo usando una struttura

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

quindi il tuo codice:

let audience = Audience.Public

funzionerà come previsto. Non è carino e ci sono alcuni aspetti negativi perché non si utilizza un "enum", non è possibile utilizzare il collegamento solo aggiungendo. Privato né funzionerà con i casi switch.


Sembra pulito. Mi chiedo quale sarebbe la migliore pratica per questo caso particolare. Preferirei usare la sintassi di struct per via della semplicità ma usare struct al posto di enum non sembra giusto, o forse sono solo io? Bene, nulla ti impedisce di dichiarare variabili costanti altrove, questa volta lo aggiungi semplicemente all'interno di una struttura in modo che sia organizzato. Pensieri?
schystz,

Esatto, funziona come variabili costanti ma più organizzato. Come ho detto prima, l'unico problema è la "custodia" e le scorciatoie ".Privato". Se stai costruendo da zero la tua app, prova ad usare "enum", usa le strutture solo se "enum" non soddisfa il tuo codice per qualche motivo. Personalmente evito le variabili delle costanti e uso sempre le strutture.
Adriano Spadoni,

Lo uso per le chiavi predefinite. Piuttosto che ricordare le chiavi predefinite all'interno di un'app, scarico le chiavi in ​​una struttura e le tiro da lì.
Adrian,

3

Esistono diversi modi per farlo. O potresti definire una funzione nell'enum che restituisce la stringa in base al valore del tipo enum:

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

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

Oppure puoi provare questo:

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

E per usarlo:

var a:Audience=Audience.Public
println(a.toRaw())

1

A partire da Swift 3.0 è possibile

var str = String(describing: Audience.friends)

1
Incredibile, ma funziona perfettamente. Molto più breve di un approccio "idiomatico". Grazie!
Roman
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.