Swift: Ubah nilai enum menjadi String?

150

Diberikan enum berikut:

enum Audience {
    case Public
    case Friends
    case Private
}

Bagaimana cara mendapatkan string "Public"dari audiencekonstanta di bawah ini?

let audience = Audience.Public
ma11hew28
sumber
2
silakan periksa jawaban ini, ini mungkin memberi Anda beberapa ide tentang bagaimana Anda dapat mencapai hal seperti itu: stackoverflow.com/questions/24648726/enums-with-data-in-swift/…
holex
di Swift 2 dan xcode7 Anda tidak perlu mengubah apa pun ke kode Anda, cukup gunakanprint("\(audience)")
gbdavid
7
Saya benci ecoscape Swift sekarang dipenuhi dengan jawaban yang sangat kuno seperti ini. Pada XCode8.2 / Swift3, semudahString(describing: yourEnumValue)
Travis Griggs
@TravisGriggs Ini tidak berfungsi untuk Xcode 11.4 lagi
DawnSong

Jawaban:

168

Tidak yakin di versi Swift mana fitur ini ditambahkan, tetapi saat ini ( Swift 2.1 ) Anda hanya memerlukan kode ini:

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

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

Saat string digunakan untuk nilai mentah, nilai implisit untuk setiap kasus adalah teks nama kasus tersebut .

[...]

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

Dalam contoh di atas, CompassPoint.south memiliki nilai mentah implisit "selatan", dan seterusnya.

Anda mengakses nilai mentah kasus enumerasi dengan properti rawValue:

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

Sumber.

DevAndArtist
sumber
8
di xcode7.3 swift2.2, jika saya melakukan hal-hal seperti: print("appState: \(application.applicationState)") i get appState: UIApplicationState yang merupakan jenis dan bukan representasi string aktual dari nilai enum. Apakah saya melewatkan sesuatu di sini? (PS: untuk rawValue saya hanya mendapatkan nilai Int ...)
Martin
@Cyrus skenario Anda berbeda dari yang ditanyakan di utas ini. .rawValueakan mengembalikan nilai mentah enum Anda. Milikmu public enum UIApplicationState : Intmemang tipe Int. Anda juga belum pernah membaca jawaban saya yang mengutip dari dokumen Apple. ... Jika Anda masih ingin mengonversi UIApplicationStateke string, saya sarankan Anda untuk memperluas UIApplicationStatedengan properti extension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }
penghitungan
Tidak menyelesaikan masalah dengan enum yang bukan tipe String
denis631
1
@ denis631 apa maksudmu? Jenis mentah enum bisa apa saja. Enum bahkan dapat disesuaikan OptionSetjika Anda benar-benar menginginkannya. Dan pertanyaan aslinya adalah tentang Strings.
DevAndArtist
1
jika enum saya ditulis seperti ini, enum Test: Int {case A, B}, rawValue tentu saja akan mengembalikan int kembali, yang kita cari adalah cara untuk mendapatkan nama case sebagai String. Inilah yang dilakukan @DanilShaykhutdinov. Lihatlah jawabannya dan di pertanyaan awal enum tidak memiliki tipe, bukan String atau Int.
denis631
218

Antarmuka idiomatik untuk 'mendapatkan String' adalah menggunakan CustomStringConvertible antarmuka dan mengakses descriptionpengambil. Tentukan Anda enumsebagai:

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

Beraksi:

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

Diperbarui : Untuk Swift> = 2.0, diganti PrintabledenganCustomStringConvertible

Catatan : Menggunakan CustomStringConvertiblememungkinkan Foountuk mengadopsi tipe mentah yang berbeda. Misalnya enum Foo : Int, CustomStringConvertible { ... }mungkin. Kebebasan ini bisa bermanfaat.

GoZoner
sumber
2
Cara lain yang lebih pendek untuk membuat string println adalah: "String untuk 'foo' is (foo)"
John MP Knox
3
@ JohnM.P.Knox jangan lupa garis miring ke belakang seperti pada "String untuk 'foo' adalah \ (foo)". Sunting OK, itu editor yang menyingkirkannya, saya harus memasukkan 2 dari mereka agar muncul
zmit
Apa gunanya CustomStringConvertiblejika ini bekerja dengan baik tanpanya?
Daniel van der Merwe
3
CustomStringConvertiblememungkinkan / mengharuskan Anda untuk menentukan descriptionyang memungkinkan Anda memutuskan string apa yang akan digunakan untuk setiap kasus enum - ini penting untuk internasionalisasi pasti dan mungkin keterbacaan kode. Jika Anda tidak peduli tentang itu, maka Anda dapat menggunakan 'enum Foo: String {/ * ... * /} `
GoZoner
2
Ini adalah jawaban yang benar jika enum Anda bukan String atau Anda menginginkan string yang berbeda maka rawValue. @ denis631
Haagenti
35

Di swift 3, Anda bisa menggunakan ini

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

dari Swift cara menggunakan enum untuk mendapatkan nilai string

Danil Shaykhutdinov
sumber
4
Ini sangat membantu, terutama jika saya enumtidak didasarkan pada Strings
daspianist
1
"\(enumValue)"Melakukan hal yang sama. ^^
eonist
Ini jawaban yang lebih baik. Tidak perlu membuat tipe String enum Anda.
scord
32

Untuk saat ini, saya akan mendefinisikan ulang enum sebagai:

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

sehingga saya dapat melakukan:

audience.toRaw() // "Public"

Tapi, bukankah definisi enum baru ini berlebihan? Dapatkah saya menyimpan definisi enum awal dan melakukan sesuatu seperti:

audience.toString() // "Public"
ma11hew28
sumber
3
Pada Xcode 7 Beta 3 Anda cukup menulis jawaban Anda tetapi tanpa = Stringkarena secara otomatis mendapat nilai mentah (nama kasus) jika Anda tidak memberikannya.
Qbyte
3
Alih-alih .toString () sekarang gunakan .rawValue
SoftDesigner
Di Swift 1.2 Anda dapat menggunakan: println (Audience.Friends.rawValue)
Oleg Popov
26

Saya suka menggunakan Printabledengan Raw Values.

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

    var description: String {
        return self.rawValue
    }
}

Kemudian kita bisa melakukan:

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

atau

println("The value of Public is \(Audience.Public)") 
// Prints "The value of Public is Public"
Sederhana99
sumber
1
Saya suka cara ini lebih baik daripada jawaban yang dipilih karena saya bisa melakukannyaAudience(rawValue: "Friends")
tidwall
12

Diperbarui untuk rilis Xcode 7 GM. Ini berfungsi seperti yang diharapkan sekarang - terima kasih 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
sumber
2
Di Swift 2.0, menyesuaikan dengan CustomStringConvertiblesebenarnya akan memungkinkan penggunaan hanya print(r)dalam kasus ini.
matm
Di Xcode 7 beta 4, reflect () tampaknya telah dinonaktifkan demi Mirror (mencerminkan: x). Namun, objek yang dikembalikan memiliki struktur yang berbeda.
GSnyder
1
Perbarui jawabannya
pronebird
10

Ini tidak bisa lebih sederhana dari ini di Swift 2 dan Xcode 7 terbaru (tidak perlu menentukan jenis enum, atau .rawValue, deskriptor dll ...)

Diperbarui untuk Swift 3 dan Xcode 8:

    enum Audience {
        case Public
        case Friends
        case Private
    }

    let audience: Audience = .Public  // or, let audience = Audience.Public
    print(audience) // "Public"
gbdavid.dll
sumber
Bekerja sempurna dengan enum yang didukung Int saya
chrislarson
Hanya pengamatan: Ini berfungsi untuk enum yang dibuat sendiri tetapi tidak berfungsi untuk sesuatu seperti HKWorkoutActivityType
Ace Green
Serta untuk string yang dilokalkan;)
Eugene Braginets
2
Pertanyaan aslinya adalah tentang mengubah nilai enum menjadi string dalam enum Anda sendiri, jadi itulah yang saya berikan jawaban untuk ... Jika Anda ingin menangani UIKit / AppKit Enums, tentu saja itu cerita yang berbeda.
gbdavid
1
@gbdavid - Apakah ada Q untuk UIKit / AppKit Enums? Saya mencari di Google dan tidak dapat menemukannya. Saya dapat mengirimkan Q jika diperlukan.
benc
8

Contoh cepat 3 ke atas jika menggunakan Ints di 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
sumber
Solusi yang elegan. "\ (kategori)" atau secara langsung String (mendeskripsikan: kategori) juga akan berfungsi. Bahkan untuk enum Int.
t1ser
8

Bagi siapa pun yang membaca contoh dalam bab "A Swift Tour" dari "Bahasa Pemrograman Swift" dan mencari cara untuk menyederhanakan metode simpleDescription (), mengonversi enum itu sendiri ke String dengan melakukan String(self)akan melakukannya:

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
sumber
2
Pastikan Anda tidak menggunakan enum dengan "@objc". Itu menyebabkan pendekatan ini gagal.
Matt Bearson
5

Setelah mencoba beberapa cara berbeda, saya menemukan bahwa jika Anda tidak ingin menggunakan:

let audience = Audience.Public.toRaw()

Anda masih dapat mengarsipkannya menggunakan struct

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

lalu kode Anda:

let audience = Audience.Public

akan bekerja seperti yang diharapkan. Tidak cantik dan ada beberapa kelemahan karena Anda tidak menggunakan "enum", Anda tidak dapat menggunakan pintasan yang hanya menambahkan. Pribadi juga tidak akan berfungsi dengan kasus sakelar.

Adriano Spadoni
sumber
Terlihat rapi. Saya ingin tahu apa yang akan menjadi praktik terbaik untuk kasus khusus ini. Saya lebih suka menggunakan sintaks struct karena kesederhanaan tetapi menggunakan struct daripada enum tampaknya tidak benar, atau mungkin hanya saya? Nah, tidak ada yang menghalangi Anda untuk hanya mendeklarasikan variabel konstan di tempat lain, kali ini Anda hanya menambahkannya di dalam struct sehingga terorganisir. Pikiran?
schystz
Tepat, Ini berfungsi sebagai variabel konstan tetapi lebih terorganisir. Seperti yang saya katakan sebelumnya, satu-satunya masalah adalah "switch case" dan pintasan ".Private". Jika Anda membuat aplikasi dari awal, coba gunakan "enum", gunakan struct hanya jika "enum" tidak memenuhi kode Anda karena beberapa alasan. Saya pribadi menghindari variabel konstanta dan selalu menggunakan struct sebagai gantinya.
Adriano Spadoni
Saya menggunakan ini untuk kunci default. Daripada mengingat kunci default dalam sebuah aplikasi, saya membuang kunci ke dalam struct dan menariknya dari sana.
Adrian
4

Ada banyak cara untuk melakukan ini. Anda bisa menentukan fungsi dalam enum yang mengembalikan string berdasarkan nilai tipe enum:

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

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

Atau Anda bisa mencoba ini:

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

Dan untuk menggunakannya:

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

Mulai dari Swift 3.0 Anda bisa

var str = String(describing: Audience.friends)
iosMentalist
sumber
1
Luar biasa, tapi itu bekerja dengan sempurna. Jauh lebih pendek dari pendekatan "idiomatik". Terima kasih!
Roman
0

Gunakan cara Ruby

var public: String = "\(Audience.Public)"
birdy
sumber
0

Satu cara lagi

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