Swift: Converter valor de enum em String?


141

Dado o seguinte enum:

enum Audience {
    case Public
    case Friends
    case Private
}

Como obtenho a string "Public"da audienceconstante abaixo?

let audience = Audience.Public

2
por favor, verifique esta resposta, ele pode lhe dar algumas idéias sobre como você pode conseguir tal coisa: stackoverflow.com/questions/24648726/enums-with-data-in-swift/...
holex

no Swift 2 e no xcode7, você não precisa alterar nada no seu código, basta usarprint("\(audience)")
gbdavid

7
Eu odeio que o Swift ecoscape agora esteja cheio de respostas muito antigas assim. No XCode8.2 / Swift3, é tão fácil quantoString(describing: yourEnumValue)
Travis Griggs

@TravisGriggs Ele não funciona mais para o Xcode 11.4
DawnSong

Respostas:


156

Não sabe em qual versão Swift esse recurso foi adicionado, mas agora ( Swift 2.1 ) você só precisa deste código:

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

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

Quando cadeias são usadas para valores brutos, o valor implícito para cada caso é o texto do nome desse caso .

[...]

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

No exemplo acima, CompassPoint.south tem um valor bruto implícito de "sul" e assim por diante.

Você acessa o valor bruto de um caso de enumeração com sua propriedade rawValue:

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

Fonte.


8
no xcode7.3 swift2.2, se eu fizer coisas como: print("appState: \(application.applicationState)") eu recebo appState: UIApplicationState qual é o tipo e não a representação real da string do valor de enumeração. Estou faltando alguma coisa aqui? (PS: para RawValue eu apenas obter o valor Int ...)
Martin

@Cyrus, seu cenário é diferente do que foi solicitado neste tópico. .rawValueretornará o valor bruto da sua enumeração. O seu é o public enum UIApplicationState : Intque é realmente do tipo Int. Você também nunca leu minha resposta, que tem uma citação dos documentos da Apple. ... Se você ainda deseja converter UIApplicationStatepara string eu sugiro que você estenda UIApplicationStatecom uma propriedade personalizada calculadoextension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }
DevAndArtist

Não resolve o problema com ter enums de não tipo String
denis631

1
@ denis631 o que você quer dizer? O tipo bruto de um enum pode ser qualquer coisa. Um enum pode estar em conformidade, OptionSetse você realmente quiser. E a pergunta original é sobre Strings de qualquer maneira.
DevAndArtist

1
se meu enum é escrito assim, enum Test: Int {case A, B}, o rawValue retornará naturalmente int de volta, o que estamos procurando é uma maneira de obter o nome do caso como uma String. Foi exatamente isso que @DanilShaykhutdinov fez. Veja a resposta dele e, na pergunta original, o enum não tem tipo, nem uma String ou Int.
Denis631 22/0318

209

A interface idiomática para 'obter uma String' é usar a CustomStringConvertible interface e acessar o descriptiongetter. Defina seu 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"
    }
  }
}

Em ação:

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

Atualizado : para Swift> = 2.0, substituído PrintableporCustomStringConvertible

Nota : Usar CustomStringConvertiblepermite Fooadotar um tipo bruto diferente. Por exemplo, enum Foo : Int, CustomStringConvertible { ... }é possível. Essa liberdade pode ser útil.


2
Outra maneira mais curta de criar a string println é: "A string para 'foo' é (foo)"
John MP Knox

3
@ JohnM.P.Knox não se esqueça da barra invertida, como em "String para 'foo' é \ (foo)". Editar OK, é o editor de se livrar dele, eu tinha para entrar 2 deles para que ele aparecer
zmit

Qual é o sentido de CustomStringConvertiblese isso funcionar tão bem sem ele?
Daniel van der Merwe 15/01

3
CustomStringConvertiblepermite / requer que você defina descriptionqual permite que você decida qual string usar para cada caso de enum - isso é importante para a internacionalização com certeza e talvez a legibilidade do código. Se você não se preocupam com aqueles, então você pode usar 'enum Foo: String {/ * ... * /} `
GoZoner

2
Esta é a resposta correta se o seu enum não for uma String ou se você desejar uma string diferente do valor bruto. @ denis631
Haagenti

32

Por enquanto, redefinirei a enum como:

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

para que eu possa fazer:

audience.toRaw() // "Public"

Mas, essa nova definição de enum não é redundante? Posso manter a definição inicial de enum e fazer algo como:

audience.toString() // "Public"

3
No Xcode 7 Beta 3, você pode apenas escrever sua resposta, mas sem o = Stringporque ele recebe automaticamente um valor bruto (nome do caso), se você não fornecer nenhum.
Qbyte

3
Em vez de .toString () agora use .rawValue
SoftDesigner

No Swift 1.2, você pode usar: println (Audience.Friends.rawValue)
Oleg Popov


24

Eu gosto de usar Printablecom Raw Values.

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

    var description: String {
        return self.rawValue
    }
}

Então nós podemos fazer:

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

ou

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

1
Eu gosto desta maneira melhor do que a resposta selecionada, porque eu posso fazerAudience(rawValue: "Friends")
tidwall

12

Atualizado para o lançamento do Xcode 7 GM. Funciona como seria de esperar agora - obrigado 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
No Swift 2.0, a conformidade CustomStringConvertiblepermitiria realmente usar apenas print(r)neste caso.
matm

No Xcode 7 beta 4, reflect () parece ter sido desativado em favor do Mirror (refletindo: x). No entanto, o objeto retornado possui uma estrutura diferente.
31915 GSnyder

1
Atualize a resposta, por favor
Ben Sinclair

10

Não poderia ser mais simples do que isso no Swift 2 e no Xcode 7 mais recente (não há necessidade de especificar o tipo de enum ou .rawValue, descritores etc ...)

Atualizado para 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"

Funcionou perfeitamente com a minha Int apoiado enums
chrislarson

Apenas uma observação: isso funciona para auto criado enums mas não funciona para algo como HKWorkoutActivityType
Ace Verde

Bem como para seqüências de caracteres localizadas;)
Eugene Braginets

2
A pergunta original era sobre a conversão de valor de enumeração em sequência em suas próprias enumerações, e foi isso que eu dei uma resposta ... Se você quiser lidar com as enums do UIKit / AppKit, é claro que é uma história diferente.
Gdavid # 31/16

1
@gbdavid - Existe um Q para UIKit / AppKit Enums? Pesquisei no Google e não consegui encontrar. Posso enviar Q, se necessário.
benc

8

Um exemplo rápido 3 e acima se estiver usando Ints no 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

Uma solução elegante. "\ (category)" ou diretamente String (descrevendo: category) também funcionariam. Mesmo para enums Int.
t1ser

8

Para quem lê o exemplo no capítulo "Um tour Swift" de "A linguagem de programação Swift" e procura uma maneira de simplificar o método simpleDescription (), a conversão da enum em String ao String(self)fazer isso:

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
Apenas verifique se você não está usando a enumeração com "@objc". Isso faz com que essa abordagem falhe.
Matt Bearson 01/08/19

5

Depois de tentar algumas maneiras diferentes, descobri que se você não quiser usar:

let audience = Audience.Public.toRaw()

Você ainda pode arquivá-lo usando uma estrutura

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

então seu código:

let audience = Audience.Public

funcionará como esperado. Não é bonito e há algumas desvantagens porque você não está usando uma "enumeração", não é possível usar o atalho apenas adicionando .Private nem funcionará com casos de opção.


Parece arrumado. Gostaria de saber qual seria a melhor prática para este caso em particular. Eu preferiria usar a sintaxe struct por causa da simplicidade, mas usar struct em vez de enum não parece certo, ou talvez seja apenas eu? Bem, nada impede que você apenas declare variáveis ​​constantes em qualquer outro lugar, desta vez, basta adicioná-lo dentro de uma estrutura para que ela seja organizada. Pensamentos?
schystz

Exatamente, funciona como variáveis ​​constantes, mas mais organizadas. Como eu disse antes, o único problema é o "switch case" e os atalhos ".Private". Se você estiver criando a partir do zero seu aplicativo, tente usar "enum", use estruturas apenas se o "enum" não satisfizer seu código por algum motivo. Pessoalmente, evito variáveis ​​constantes e sempre use estruturas.
Adriano Spadoni

Eu uso isso para chaves padrão. Em vez de lembrar as chaves padrão em um aplicativo, eu despejo as chaves em uma estrutura e as puxo de lá.
Adrian

3

Existem várias maneiras de fazer isso. Você pode definir uma função no enum que retorne a string com base no valor do tipo de enum:

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

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

Ou você pode tentar o seguinte:

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

E para usá-lo:

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

1

A partir do Swift 3.0, você pode

var str = String(describing: Audience.friends)

1
Inacreditável, mas isso funciona perfeitamente. Muito mais curto que a abordagem "idiomática". Obrigado!
Roman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.