198

Given the following enum:

enum Audience {
    case Public
    case Friends
    case Private
}

How do I get the string "Public" from the audience constant below?

let audience = Audience.Public
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
  • 3
    please check this answer, it may give you some ideas about how you can achieve such thing: http://stackoverflow.com/questions/24648726/enums-with-data-in-swift/24650006#24650006 – holex Jul 11 '14 at 15:18
  • 1
    in Swift 2 and xcode7 you don't need to change anything to your code, just use `print("\(audience)")` – gbdavid Dec 08 '15 at 15:57
  • 8
    I hate that the Swift ecoscape is now filled with very dated answers like this. As Of XCode8.2/Swift3, it's as easy as `String(describing: yourEnumValue)` – Travis Griggs Jan 13 '17 at 00:09
  • @TravisGriggs It does not work for Xcode 11.4 any longer – DawnSong Mar 04 '20 at 05:36
  • 1
    Possible duplicate of [How to get the name of enumeration value in Swift?](https://stackoverflow.com/questions/24113126/how-to-get-the-name-of-enumeration-value-in-swift) – pkamb Mar 16 '20 at 22:57
  • You can use rawValue property of enum . Eg. Audience.Public.rawValue: – Jayprakash Dubey Aug 25 '20 at 06:46

20 Answers20

280

The idiomatic interface for 'getting a String' is to use the CustomStringConvertible interface and access the description getter. You could specify the 'raw type' as String but the use of description hides the 'raw type' implementation; avoids string comparisons in switch/case and allows for internationalization, if you so desire. Define your enum as:

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 action:

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

Updated: For Swift >= 2.0, replaced Printable with CustomStringConvertible

Note: Using CustomStringConvertible allows Foo to adopt a different raw type. For example enum Foo : Int, CustomStringConvertible { ... } is possible. This freedom can be useful.

GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • 2
    Another shorter way to create the println string is: "String for 'foo' is \(foo)" – John M. P. Knox Nov 11 '14 at 20:53
  • 3
    @JohnM.P.Knox don't forget the back-slash as in "String for 'foo' is \\(foo)". **Edit** OK, it's the editor getting rid of it, I had to enter 2 of them in order for it to show up – zmit Feb 05 '15 at 13:51
  • What's the point in `CustomStringConvertible` if this works just as fine without it? – Daniel van der Merwe Jan 15 '16 at 12:01
  • 3
    `CustomStringConvertible` allows/requires you to define `description` which lets you decide what string to use for each enum case - this is important for internationalization surely and perhaps code readability. If you don't care about those, then you can use 'enum Foo : String { /* ... */ }` – GoZoner Jan 15 '16 at 16:49
  • 2
    This is the correct answer if your enum is not a String or you want a different string then the rawValue. @denis631 – Haagenti Apr 13 '18 at 10:11
  • @Haagenti this is not what the OP was asking. quote: > ```How do I get the string "Public" from the audience constant below? let audience = Audience.Public```. Or at least the answer is not complete. Code duplication or just copy pasting is never good. – denis631 Apr 13 '18 at 14:47
  • Great answer. Can this be used to get a `Foo` type from a `String` that matches its description? – agirault Dec 04 '18 at 16:57
  • Thanks a lot. Your solution helped me solve my problem. Great work!! – Dian Nov 15 '19 at 20:20
  • The answer below by "DevAndArtist" takes a lot less code and has less potential for mistakes. – Andrew Koster Feb 05 '23 at 02:32
229

Not sure in which Swift version this feature was added, but right now (Swift 2.1) you only need this code:

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

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

When strings are used for raw values, the implicit value for each case is the text of that case’s name.

[...]

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

In the example above, CompassPoint.south has an implicit raw value of "south", and so on.

You access the raw value of an enumeration case with its rawValue property:

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

Source.

DevAndArtist
  • 4,971
  • 1
  • 23
  • 48
  • 8
    in xcode7.3 swift2.2, if i do things like: `print("appState: \(application.applicationState)")` i get `appState: UIApplicationState` which is the type and not the actual string representation of the enum value. Am I missing something here? (PS: for rawValue I just get the Int value...) – Martin Mar 25 '16 at 05:43
  • @Cyrus your scenario is different from that was asked in this thread. `.rawValue` will return the raw value of your enum. Yours is `public enum UIApplicationState : Int` which is indeed of type `Int`. You also have never read my answer which has a quote from Apple docs. ... If you still want to convert `UIApplicationState` to string I'd suggest you to extend `UIApplicationState` with a custom computed property `extension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }` – DevAndArtist Mar 25 '16 at 09:31
  • Doesn't solve the issue with having enums of not String type – denis631 Mar 22 '18 at 14:07
  • 1
    @denis631 what do you mean? The raw type of an enum can be anything. An enum can even conform to `OptionSet` if you really want to. And the original question is about Strings anyways. – DevAndArtist Mar 22 '18 at 14:10
  • 1
    if my enum is written like this, enum Test: Int { case A, B }, the rawValue will of course return int back, what we are looking for is a way to get the name of the case as a String. This is exactly what @DanilShaykhutdinov did. Look at his answer and in the original question the enum has no type, not a String or Int. – denis631 Mar 22 '18 at 14:21
  • @denis631 that is correct. For that there is no general solution and you have to fallback to one of the other solutions mentioned in this thread. That said if you don't care about the raw type then the solution I've shown is the most convenient one. In case you need a different raw type then you will have to do it yourself and map each case to a string. – DevAndArtist Mar 22 '18 at 14:24
  • @DevAndArtist glad that you got my point. ```String(describing: concreteEnumCase)```, will create a string of the enum case, which is pretty sweet. Therefore you have no dependency on enum cases and can add or remove cases without the need of modifying this toString function – denis631 Mar 22 '18 at 15:08
52

In swift 3, you can use this

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

from Swift how to use enum to get string value

Community
  • 1
  • 1
Danil Shaykhutdinov
  • 2,027
  • 21
  • 26
  • 4
    This is really helpful, especially if my `enum` is not based on `String`s – daspianist Mar 31 '17 at 17:42
  • 3
    `"\(enumValue)"` Does the same thing. ^^ – Sentry.co May 11 '17 at 16:00
  • This is a better answer. Doesn't require making your enum String type. – scord Apr 12 '19 at 19:25
  • 1
    `String(describing:)` should *never* be used to convert anything to String, it's not its purpose and will give unexpected results in many cases. Better use string interpolation or string initializers. – Eric Aya Jun 20 '21 at 10:14
  • @EricAya According to..? That's [exactly what it's for](https://developer.apple.com/documentation/swift/string/init(describing:)-67ncf): _"Use this initializer to convert an instance of any type to its preferred representation as a String instance."_ – kwiknik Mar 04 '23 at 20:43
  • @kwiknik "preferred representation" is the important idea. Implementation can change, and results can be undefined and misleading, it's interpreted and unspecified, it's a representation depending on protocol conformance, it's a *description*, not a conversion. It's useful for debugging and reflection, but should not be used when you expect strict conversion to string - in that case, use the normal init (or interpolation), not the describing init. – Eric Aya Mar 04 '23 at 21:11
36

For now, I'll redefine the enum as:

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

so that I can do:

audience.toRaw() // "Public"

But, isn't this new enum definition redundant? Can I keep the initial enum definition and do something like:

audience.toString() // "Public"
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
29

I like to use Printable with Raw Values.

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

    var description: String {
        return self.rawValue
    }
}

Then we can do:

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

or

println("The value of Public is \(Audience.Public)") 
// Prints "The value of Public is Public"
Simple99
  • 1,038
  • 11
  • 20
  • 1
    I like this way better than the selected answer because I can do `Audience(rawValue: "Friends")` – tidwall Mar 29 '15 at 01:12
13

A swift 3 and above example if using 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
tsukimi
  • 1,605
  • 2
  • 21
  • 36
  • 1
    An elegant solution. "\\(category)" or directly String(describing:category) would also work. Even for Int enums. – t1ser May 02 '20 at 22:22
  • This is my prefered solution. It allows to get the enum element's index and the associated String value – Paul Ollivier Apr 09 '21 at 10:14
12

Updated for the release of Xcode 7 GM. It works as one would hope now--thanks 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
  • 17,361
  • 4
  • 65
  • 80
  • 2
    In Swift 2.0, conforming to `CustomStringConvertible` would actually allow using just `print(r)` in this case. – matm Jul 22 '15 at 15:42
  • In Xcode 7 beta 4, reflect() seems to have been disabled in favor of Mirror(reflecting: x). However, the returned object has a different structure. – GSnyder Jul 29 '15 at 19:50
  • 1
    Update the answer please – pronebird Sep 14 '15 at 13:54
11

It couldn't get simpler than this in Swift 2 and the latest Xcode 7 (no need to specify enum type, or .rawValue, descriptors etc...)

Updated for Swift 3 and Xcode 8:

    enum Audience {
        case Public
        case Friends
        case Private
    }

    let audience: Audience = .Public  // or, let audience = Audience.Public
    print(audience) // "Public"
shim
  • 9,289
  • 12
  • 69
  • 108
gbdavid
  • 1,639
  • 18
  • 40
  • Worked perfectly with my Int backed enums – chrislarson Dec 29 '15 at 05:12
  • Just an observation: This works for self created enums but doesn't work for something like HKWorkoutActivityType – Ace Green Mar 30 '16 at 01:24
  • As well as for localized strings ;) – Eugene Braginets Jun 23 '16 at 10:26
  • Don't work for me. `let type : UIKeyboardType = .EmailAddress print("\(type)")` It prints > UIKeyboardType – Payal Maniyar Sep 10 '16 at 06:15
  • 2
    The original question was about converting enum value to string in your own enums, so that's what I gave an answer for... If you'll like to handle UIKit/AppKit Enums, of course it's a different story. – gbdavid Oct 31 '16 at 10:16
  • Doesn't work for live values like `avplayeritem.status`. – Jonny Mar 27 '17 at 06:31
  • It's obviously the simplest method and it has limitations... It has fulfilled the requirement asked in the original question... if it doesn't suit your needs, you may look at more complex implementations in other contributions above... – gbdavid Mar 27 '17 at 11:07
  • 1
    @gbdavid - Is there a Q for UIKit/AppKit Enums? I googled and couldn't find it. I can submit Q if that is needed. – benc Jun 11 '18 at 19:38
  • Sure! that'll be a good idea @benc, as this question is mainly for plain Swift enums :) – gbdavid Jun 12 '18 at 20:16
  • great solution let stringValue = "\(audience)" print(stringValue) // "Public" – carlachip Aug 13 '21 at 03:35
9

You can also use "\(enumVal)" Here is an example :

enum WeekDays{ case Sat, Sun, Mon, Tue, Wed, The, Fri } 

let dayOfWeek: String = "\(WeekDays.Mon)"

Tried and tested in Swift 5

Tech guy
  • 125
  • 1
  • 8
8

After try few different ways, i found that if you don't want to use:

let audience = Audience.Public.toRaw()

You can still archive it using a struct

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

then your code:

let audience = Audience.Public

will work as expected. It isn't pretty and there are some downsides because you not using a "enum", you can't use the shortcut only adding .Private neither will work with switch cases.

Adriano Spadoni
  • 4,540
  • 1
  • 25
  • 25
  • Looks neat. I wonder what would be the best practice for this particular case. I would prefer using the struct syntax because of the simplicity but using struct instead of enum doesn't seem right, or maybe it is just me? Well, nothing prevents you on just declaring constant variables anywhere else, this time you just add it inside a struct so its organized. Thoughts? – schystz Oct 15 '15 at 22:31
  • Exactly, It works as constant variables but more organised. As I said before the only problem is the "switch case" and the shortcuts ".Private". If you are building from scratch your app, try to go with "enum", use structs only if the "enum" doesn't satisfy your code for some reason. I'm personally avoid constants variables an always use structs instead. – Adriano Spadoni Oct 16 '15 at 11:38
  • I use this for default keys. Rather than remembering default keys within an app, I dump the keys in a struct and pull them from there. – Adrian Oct 15 '17 at 10:30
8

For anyone reading the example in "A Swift Tour" chapter of "The Swift Programming Language" and looking for a way to simplify the simpleDescription() method, converting the enum itself to String by doing String(self) will do it:

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)
        }
     }
 }
pkamb
  • 33,281
  • 23
  • 160
  • 191
Vivek Gani
  • 1,283
  • 14
  • 28
5

Modern, minimalist way

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

    func callAsFunction() -> String {
        rawValue
    }
}

let audience = Audience.Public() // "Public"
arkir
  • 1,336
  • 2
  • 10
  • 9
  • 2
    There is no reason to use `callAsFunction` here other than to flaunt that you know what `callAsFunction` is. Delete this! –  Apr 30 '23 at 16:02
  • 1
    "Flaunt"? It is language feature for a reason. You can use it to be more concise, for ex this case you don't need to type rawValue every time. – arkir Apr 30 '23 at 16:21
  • It has reasons. This is not one of them. Nobody else will understand this code. Delete it. –  Apr 30 '23 at 18:41
  • > "Minimalist" Oh yeah, very minimal :) Capitalized case names, callable instances, explicit raw values and ability to mix up serialized string version with the original type in just 2 simple round brackets. As if, turning into string is main goal of this enum's existence. – Isaaс Weisberg Sep 01 '23 at 08:19
4

There are multiple ways to do this. Either you could define a function in the enum which returns the string based on the value of enum type:

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

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

Or you could can try this:

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

And to use it:

var a:Audience=Audience.Public
println(a.toRaw())
m0bi5
  • 8,900
  • 7
  • 33
  • 44
Dhruv Ramani
  • 2,633
  • 2
  • 22
  • 29
4

Starting from Swift 3.0 you can

var str = String(describing: Audience.friends)
iosMentalist
  • 3,066
  • 1
  • 30
  • 40
  • 3
    Unbelievable, but that perfectly works. Much shorter than "idiomatic" approach. Thanks! – Roman Jul 24 '20 at 08:31
4

Use Ruby way

var public: String = "\(Audience.Public)"
beerdy
  • 73
  • 5
2

One more way

public enum HTTP{
case get
case put
case delete
case patch
var value: String? {
return String(describing: self)
}
2

Friendly by guides if you need to use static strings as enum values:

class EncyclopediaOfCats {
    struct Constants {
        static var playHideAndSeek: String { "Play hide-and-seek" }
        static var eat: String { "Eats" }
        static var sleep: String { "Sleep" }
        static var beCute: String { "Be cute" }
    }
}

enum CatLife {
    case playHideAndSeek
    case eat
    case sleep
    case beCute

    typealias RawValue = String
    
    var rawValue: String {
        switch self {
        case .playHideAndSeek:
            return EncyclopediaOfCats.Constants.playHideAndSeek
        case .eat:
            return EncyclopediaOfCats.Constants.eat
        case .sleep:
            return EncyclopediaOfCats.Constants.sleep
        case .beCute:
            return EncyclopediaOfCats.Constants.beCute
        }
    }
    
    init?(rawValue: CatLife.RawValue) {
        switch rawValue {
        case EncyclopediaOfCats.Constants.playHideAndSeek:
            self = .playHideAndSeek
        case EncyclopediaOfCats.Constants.eat:
            self = .eat
        case EncyclopediaOfCats.Constants.sleep:
            self = .sleep
        case EncyclopediaOfCats.Constants.beCute:
            self = .beCute
        default:
            self = .playHideAndSeek
        }
    }
}
CAHbl463
  • 102
  • 7
  • Why do you need to use static strings? Anyway, since you can explicitly assign [raw values](https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html#ID149), couldn't you just do the following? `enum CatLife: String { case playHideAndSeek = EncyclopediaOfCats.Constants.playHideAndSeek /* ... */ }` – ma11hew28 Mar 26 '21 at 18:04
2

XCode 14.0.1/Swift 5.7:

This is something that should be simple to achieve, but that is quite confusing, with some pitfalls!

Most answers here explain how to associate strings to each enum values, or to create enums of explicit Strings, but is only possible when you are creating your own enums.

In case of enums already existing, like numerous enums in Apple's APIs, one could really want to convert enums values to String.

To take a concrete example, if one wants to display NWConnection.States values in a SwiftUI Text view.

According to some answers, and assuming that we have something like:

Class tcpClient() {
    var connection: NWConnection
    (...)

then

Text("Current state: \(tcpClient.connection.state)")

should work. But you get a "No exact matches in call to instance method 'appendInterpolation'" error.

A reason to explain this behaviour is because despite being described as enum in Apple's documentation, some enumerations are in fact not Swift enumerations, but C-Style enumerations. And according to Apple, Swift can't print the text version, because all it has at runtime is enum's number value. This could be the case for quite some APIs. See: https://stackoverflow.com/a/70910402/5965609

Other solution proposed here is:

Text(String(describing: tcpClient.connection.state))

Seems to work, but @Eric Aya comment here says : String(describing:) should never be used to convert anything to String, it's not its purpose and will give unexpected results in many cases. Better use string interpolation or string initializers.

So, in case of C-Style enumarations from APIs or other imported code, the only viable solution seems to have a function with a switch case to associate Strings to each enum's value.

Gerald B.
  • 31
  • 4
  • 1
    The original question's title is "Swift: Convert enum value to String?" but most of the other answers told how to create enums with strings *associated* to values, so did not really answered the question. I'm discussing how to really *convert* enum values to String, taking a real case to illustrate it (NWConnection States but could have been anything else) and showing which pitfalls you can get into, since one of the previous answer using String interpolation doesn't work, and the other is discouraged, it seems to me that i do try to answer the question, but i do still have some doubts. – Gerald B. Oct 02 '22 at 15:57
  • 2
    Answer edited with rewording and additionnal informations – Gerald B. Oct 02 '22 at 17:06
0

I agree with all the above answers but in your enum private and the public cases can't be defined since those are default keywords. I'm including CaseIterable in my answer, it may help you to get all cases if you required to loop over.

enum Audience: String, CaseIterable {
case publicAudience
case friends
case privateAudience

var description: String {
    switch self {
    case .publicAudience: return "Public"
    case .friends: return "Friends"
    case .privateAudience: return "Private"
    }
}

static var allAudience: [String] {
    return Audience { $0.rawValue }
}

}

Ramesh Boosa
  • 198
  • 8
0

If you want a string representation of an existing enum, you can extend that enum with CustomStringConvertible.

e.g. I wanted to see a string version of UIGestureRecognizer.State

extension UIGestureRecognizer.State: CustomStringConvertible {
    public var description: String {
        switch self {
            case .possible:
                return "possible"
            case .began:
                return "began"
            case .changed:
                return "changed"
            case .ended:
                return "ended"
            case .cancelled:
                return "cancelled"
            case .failed:
                return "failed"
            @unknown default:
                return "default"
        }
    }
}

let state = UIGestureRecognizer.State.began

print("state: \(state)")

prints:

"state: began"

HangarRash
  • 7,314
  • 5
  • 5
  • 32
Rand
  • 165
  • 1
  • 1
  • 12