Swift: Chuyển đổi giá trị enum thành Chuỗi?


141

Cho enum sau:

enum Audience {
    case Public
    case Friends
    case Private
}

Làm thế nào để tôi có được chuỗi "Public"từ audiencehằng số dưới đây?

let audience = Audience.Public

2
vui lòng kiểm tra câu trả lời này, nó có thể cung cấp cho bạn một số ý tưởng về cách bạn có thể đạt được điều đó: stackoverflow.com/questions/24648726/enums-with-data-in-swift/iêu
holex

trong Swift 2 và xcode7, bạn không cần thay đổi bất cứ điều gì thành mã của mình, chỉ cần sử dụngprint("\(audience)")
gbdavid

7
Tôi ghét rằng ecoscape Swift hiện đang chứa đầy những câu trả lời rất cũ như thế này. Kể từ XCode8.2 / Swift3, nó dễ nhưString(describing: yourEnumValue)
Travis Griggs

@TravisGriggs Nó không hoạt động cho Xcode 11.4 nữa
DawnSong

Câu trả lời:


156

Không chắc chắn trong phiên bản Swift mà tính năng này đã được thêm, nhưng ngay bây giờ ( Swift 2.1 ) bạn chỉ cần mã này:

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

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

Khi các chuỗi được sử dụng cho các giá trị thô, giá trị ngầm định cho mỗi trường hợp là văn bản của tên của trường hợp đó .

[...]

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

Trong ví dụ trên, CompassPoint.south có giá trị thô ẩn là "phía nam", v.v.

Bạn truy cập giá trị thô của trường hợp liệt kê với thuộc tính rawValue của nó:

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

Nguồn.


8
trong xcode7.3 swift2.2, nếu tôi làm những việc như: print("appState: \(application.applicationState)") tôi nhận được appState: UIApplicationState đó là kiểu và không phải là biểu diễn chuỗi thực của giá trị enum. Am i thiếu cái gì ở đây? (PS: đối với rawValue, tôi chỉ nhận được giá trị Int ...)
Martin

@Cyrus kịch bản của bạn khác với kịch bản được hỏi trong chủ đề này. .rawValuesẽ trả về giá trị thô của enum của bạn. Bạn public enum UIApplicationState : Intthực sự là loại Int. Bạn cũng chưa bao giờ đọc câu trả lời của tôi trong đó có trích dẫn từ tài liệu của Apple. ... Nếu bạn vẫn muốn chuyển đổi UIApplicationStatethành chuỗi, tôi khuyên bạn nên gia hạn UIApplicationStatevới một thuộc tính được tính toán tùy chỉnhextension UIApplicationState { var toString() -> String { /* check self for all diff. cases and return something like "Active" */ }
DevAndArtist

Không giải quyết được vấn đề với việc có các loại không phải là Chuỗi
denis631

1
@ denis631 Ý bạn là gì? Loại thô của một enum có thể là bất cứ điều gì. Một enum thậm chí có thể phù hợp OptionSetnếu bạn thực sự muốn. Và câu hỏi ban đầu là về String anyways.
DevAndArtist

1
Nếu enum của tôi được viết như thế này, enum Test: Int {case A, B}, rawValue tất nhiên sẽ trả về int, điều chúng ta đang tìm kiếm là một cách để lấy tên của trường hợp là String. Đây chính xác là những gì @DanilShaykhutdinov đã làm. Nhìn vào câu trả lời của anh ta và trong câu hỏi ban đầu, enum không có loại, không phải là String hay Int.
denis631

209

Giao diện thành ngữ để 'lấy Chuỗi' là sử dụng CustomStringConvertible giao diện và truy cập descriptiongetter. Xác định của bạn enumlà:

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

Trong hành động:

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

Đã cập nhật : Đối với Swift> = 2.0, được thay thế PrintablebằngCustomStringConvertible

Lưu ý : Sử dụng CustomStringConvertiblecho phép Fooáp dụng một loại thô khác nhau. Ví dụ enum Foo : Int, CustomStringConvertible { ... }là có thể. Sự tự do này có thể hữu ích.


2
Một cách ngắn hơn khác để tạo chuỗi println là: "Chuỗi cho 'foo' là (foo)"
John MP Knox

3
@ JohnM.P.Knox đừng quên dấu gạch chéo ngược như trong "Chuỗi cho 'foo' là \ (foo)". Chỉnh sửa OK, đó là trình soạn thảo loại bỏ nó, tôi đã phải nhập 2 trong số chúng để nó hiển thị
zmit

Điều gì sẽ CustomStringConvertiblexảy ra nếu điều này hoạt động tốt như vậy mà không có nó?
Daniel van der Merwe

3
CustomStringConvertiblecho phép / yêu cầu bạn xác định descriptioncho phép bạn quyết định sử dụng chuỗi nào cho từng trường hợp enum - điều này rất quan trọng đối với việc quốc tế hóa chắc chắn và có thể dễ đọc mã. Nếu bạn không quan tâm đến những thứ đó, thì bạn có thể sử dụng 'enum Foo: String {/ * ... * /} `
GoZoner

2
Đây là câu trả lời đúng nếu enum của bạn không phải là Chuỗi hoặc bạn muốn một chuỗi khác thì rawValue. @ denis631
Haagenti

32

Bây giờ, tôi sẽ định nghĩa lại enum là:

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

để tôi có thể làm:

audience.toRaw() // "Public"

Nhưng, không phải định nghĩa enum mới này là dư thừa sao? Tôi có thể giữ định nghĩa enum ban đầu và làm một cái gì đó như:

audience.toString() // "Public"

3
Kể từ Xcode 7 Beta 3, bạn chỉ có thể viết câu trả lời của mình nhưng không có = Stringbởi vì nó tự động trở thành một giá trị thô (tên của trường hợp) nếu bạn không cung cấp bất kỳ.
Qbyte

3
Thay vì .toString () bây giờ, hãy sử dụng .rawValue
SoftDesigner

Trong Swift 1.2, bạn có thể sử dụng: println (Audience.Friends.rawValue)
Oleg Popov


24

Tôi thích sử dụng Printablevới Raw Values.

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

    var description: String {
        return self.rawValue
    }
}

Sau đó chúng ta có thể làm:

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

hoặc là

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

1
Tôi thích cách này tốt hơn câu trả lời được chọn vì tôi có thể làmAudience(rawValue: "Friends")
tidwall

12

Cập nhật cho việc phát hành Xcode 7 GM. Nó hoạt động như người ta hy vọng bây giờ - cảm ơn 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
Trong Swift 2.0, việc tuân thủ CustomStringConvertiblethực sự sẽ cho phép sử dụng chỉ print(r)trong trường hợp này.
matm

Trong Xcode 7 beta 4, Reflect () dường như đã bị vô hiệu hóa theo Mirror (Reflect: x). Tuy nhiên, đối tượng trả lại có cấu trúc khác.
GSnyder 29/07/2015

1
Vui lòng cập nhật câu trả lời
Ben Sinclair

10

Không thể đơn giản hơn điều này trong Swift 2 và Xcode 7 mới nhất (không cần chỉ định loại enum hoặc .rawValue, mô tả, v.v.)

Đã cập nhật cho Swift 3 và Xcode 8:

    enum Audience {
        case Public
        case Friends
        case Private
    }

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

Hoạt động hoàn hảo với các enums được hỗ trợ của tôi
chrislarson

Chỉ là một quan sát: Điều này hoạt động cho các enum tự tạo nhưng không hoạt động cho một cái gì đó như HKWorkoutActivityType
Ace Green

Cũng như đối với các chuỗi nội địa hóa;)
Eugene Braginets

2
Câu hỏi ban đầu là về việc chuyển đổi giá trị enum thành chuỗi trong enum của riêng bạn, vì vậy đó là điều tôi đã đưa ra câu trả lời cho ... Nếu bạn muốn xử lý UIKit / AppKit Enums, tất nhiên đó là một câu chuyện khác.
gbdavid

1
@gbdavid - Có Q cho UIKit / AppKit Enums không? Tôi googled và không thể tìm thấy nó. Tôi có thể gửi Q nếu điều đó là cần thiết.
benc

8

Ví dụ swift 3 trở lên nếu sử dụng Ints trong 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

Một giải pháp tao nhã. "\ (danh mục)" hoặc Chuỗi trực tiếp (mô tả: danh mục) cũng sẽ hoạt động. Ngay cả đối với Int enums.
t1ser

8

Đối với bất kỳ ai đọc ví dụ trong chương "Chuyến tham quan Swift" của "Ngôn ngữ lập trình Swift" và tìm cách đơn giản hóa phương thức SimpleDescrip (), chuyển đổi enum thành Chuỗi bằng cách thực hiện String(self)sẽ làm điều đó:

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
Chỉ cần chắc chắn rằng bạn không sử dụng enum với "@objc". Điều đó khiến phương pháp này thất bại.
Matt Bearson

5

Sau khi thử một vài cách khác nhau, tôi thấy rằng nếu bạn không muốn sử dụng:

let audience = Audience.Public.toRaw()

Bạn vẫn có thể lưu trữ nó bằng cách sử dụng một cấu trúc

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

sau đó mã của bạn:

let audience = Audience.Public

sẽ làm việc như mong đợi. Nó không đẹp và có một số nhược điểm vì bạn không sử dụng "enum", bạn không thể sử dụng phím tắt chỉ thêm .Private cũng không hoạt động với các trường hợp chuyển đổi.


Trông gọn gàng. Tôi tự hỏi điều gì sẽ là thực hành tốt nhất cho trường hợp cụ thể này. Tôi thích sử dụng cú pháp struct vì đơn giản nhưng sử dụng struct thay vì enum có vẻ không đúng, hoặc có thể đó chỉ là tôi? Chà, không có gì ngăn cản bạn chỉ khai báo các biến không đổi ở bất kỳ nơi nào khác, lần này bạn chỉ cần thêm nó vào bên trong một cấu trúc để nó được tổ chức. Suy nghĩ?
schystz

Chính xác, Nó hoạt động như các biến không đổi nhưng có tổ chức hơn. Như tôi đã nói trước vấn đề duy nhất là "trường hợp chuyển đổi" và các phím tắt ".Private". Nếu bạn đang xây dựng từ đầu ứng dụng của mình, hãy thử sử dụng "enum", chỉ sử dụng cấu trúc nếu "enum" không thỏa mãn mã của bạn vì một số lý do. Cá nhân tôi tránh các biến hằng và luôn luôn sử dụng các cấu trúc.
Adriano Spadoni

Tôi sử dụng điều này cho các phím mặc định. Thay vì nhớ các khóa mặc định trong một ứng dụng, tôi kết xuất các khóa trong một cấu trúc và kéo chúng từ đó.
Adrian

3

Có nhiều cách để làm điều này. Hoặc bạn có thể định nghĩa một hàm trong enum trả về chuỗi dựa trên giá trị của kiểu enum:

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

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

Hoặc bạn có thể thử điều này:

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

Và để sử dụng nó:

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

1

Bắt đầu từ Swift 3.0 bạn có thể

var str = String(describing: Audience.friends)

1
Không thể tin được, nhưng điều đó hoàn toàn hoạt động. Ngắn hơn nhiều so với cách tiếp cận "thành ngữ". Cảm ơn!
La Mã
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.