如何在Swift中获取枚举值的名称?

时间:2014-06-09 03:04:27

标签: swift enumeration

如果我的枚举值为原始Integer

enum City: Int {
  case Melbourne = 1, Chelyabinsk, Bursa
}

let city = City.Melbourne

如何将city值转换为字符串Melbourne?这种类型名称内省是否可以使用该语言?

类似的东西(这段代码不起作用):

println("Your city is \(city.magicFunction)")
> Your city is Melbourne

12 个答案:

答案 0 :(得分:116)

从Xcode 7 beta 5开始,您现在可以使用print(_:)默认打印类型名称和枚举案例,或使用String的{​​{1}}初始值设定项转换为String或字符串插值语法。所以对你的例子来说:

init(_:)

因此不再需要定义&维护一个便利功能,打开每个案例以返回一个字符串文字。此外,即使没有指定原始值类型,这也会自动适用于任何枚举。

enum City: Int { case Melbourne = 1, Chelyabinsk, Bursa } let city = City.Melbourne print(city) // prints "Melbourne" let cityName = "\(city)" // or `let cityName = String(city)` // cityName contains "Melbourne" & debugPrint(_:)可用于完全限定名称:

String(reflecting:)

请注意,您可以自定义每种情况下打印的内容:

debugPrint(city)
// prints "App.City.Melbourne" (or similar, depending on the full scope)

let cityDebugName = String(reflecting: city)
// cityDebugName contains "App.City.Melbourne"

(我还没有找到一种方法来调用这个“默认”值,例如,打印“城市是墨尔本”而不需要回到switch语句。在{}使用extension City: CustomStringConvertible { var description: String { return "City \(rawValue)" } } print(city) // prints "City 1" extension City: CustomDebugStringConvertible { var debugDescription: String { return "City (rawValue: \(rawValue))" } } debugPrint(city) // prints "City (rawValue: 1)" \(self) / description的实现会导致无限递归。)


以上评论debugDescription的{​​{1}}& String初始化程序准确描述打印的内容,具体取决于反射类型符合的内容:

init(_:)


有关此更改的信息,请参阅release notes

答案 1 :(得分:69)

目前对枚举案件没有反省。您必须手动声明它们:

enum City : String, Printable {
  case Melbourne = "Melbourne"
  case Chelyabinsk = "Chelyabinsk"
  case Bursa = "Bursa"

  var description : String {
    get {
        return self.rawValue
    }
  }
}

注意Printable协议目前无法在Playgrounds中使用。如果你想在游乐场看到字符串,你必须手动调用toRaw()

如果您需要原始类型为Int,则必须自己进行切换:

enum City : Int, Printable {
  case Melbourne = 1, Chelyabinsk, Bursa

  var description : String {
    get {
      switch(self) {
        case Melbourne:
          return "Melbourne"
        case Chelyabinsk:
          return "Chelyabinsk"
        case Bursa:
          return "Bursa"
      }
    }
  }
}

答案 2 :(得分:31)

在Swift-3中(使用Xcode 8.1测试),您可以在枚举中添加以下方法:

/**
 * The name of the enumeration (as written in case).
 */
var name: String {
    get { return String(describing: self) }
}

/**
 * The full name of the enumeration
 * (the name of the enum plus dot plus the name as written in case).
 */
var description: String {
    get { return String(reflecting: self) }
}

然后,您可以将它用作枚举实例上的常规方法调用。 它可能也适用于以前的Swift版本,但我还没有测试过它。

在你的例子中:

enum City: Int {
    case Melbourne = 1, Chelyabinsk, Bursa
    var name: String {
        get { return String(describing: self) }
    }
    var description: String {
        get { return String(reflecting: self) }
    }
}
let city = City.Melbourne

print(city.name)
// prints "Melbourne"

print(city.description)
// prints "City.Melbourne"

如果您想为所有枚举提供此功能,可以将其作为扩展程序:

/**
 * Extend all enums with a simple method to derive their names.
 */
extension RawRepresentable where RawValue: Any {
  /**
   * The name of the enumeration (as written in case).
   */
  var name: String {
    get { return String(describing: self) }
  }

  /**
   * The full name of the enumeration
   * (the name of the enum plus dot plus the name as written in case).
   */
  var description: String {
    get { return String(reflecting: self) }
  }
}

这仅适用于Swift枚举。

答案 3 :(得分:15)

对于Objective-C enum,目前似乎唯一的方法就是将CustomStringConvertible的枚举扩展为以下内容:

extension UIDeviceBatteryState: CustomStringConvertible {
    public var description: String {
        switch self {
        case .Unknown:
            return "Unknown"
        case .Unplugged:
            return "Unplugged"
        case .Charging:
            return "Charging"
        case .Full:
            return "Full"
        }
    }
}

然后将enum转换为String

String(UIDevice.currentDevice().batteryState)

答案 4 :(得分:5)

这太令人失望了。

对于你需要这些名字的情况(编译器完全知道拼写的确切拼写,但拒绝让访问 - 谢谢Swift团队!! - )但不想或不能让String成为你的基础enum,一个冗长,繁琐的替代方案如下:

enum ViewType : Int, Printable {

    case    Title
    case    Buttons
    case    View

    static let all = [Title, Buttons, View]
    static let strings = ["Title", "Buttons", "View"]

    func string() -> String {
        return ViewType.strings[self.rawValue]
    }

    var description:String {
        get {
            return string()
        }
    }
}

您可以按如下方式使用上述内容:

let elementType = ViewType.Title
let column = Column.Collections
let row = 0

println("fetching element \(elementType), column: \(column.string()), row: \(row)")

您将获得预期的结果(列的代码类似,但未显示)

fetching element Title, column: Collections, row: 0

在上面,我已经将description属性引用回string方法,但这是一个品味问题。另请注意,所谓的static变量需要通过其封闭类型的名称进行范围限定,因为编译器过于遗忘并且无法单独调用上下文...

斯威夫特团队必须真正受到指挥。他们创建了一个你不能enumerate的枚举,你可以使用enumerate的枚举是“序列”而不是enum

答案 5 :(得分:5)

除了对Swift 2.2中的枚举的String(...)(CustomStringConvertible)支持之外,还有一些对它们的反射支持。对于具有关联值的枚举案例,可以使用反射获取枚举案例的标签:

enum City {
    case Melbourne(String)
    case Chelyabinsk
    case Bursa

    var label:String? {
        let mirror = Mirror(reflecting: self)
        return mirror.children.first?.label
    }
}

print(City.Melbourne("Foobar").label) // prints out "Melbourne"

通过被破坏,我的意思是,对于“简单”枚举,上面基于反射的label计算属性只返回nil(boo-hoo)。

print(City.Chelyabinsk.label) // prints out nil

显然,在Swift 3之后,反思的情况应该会好转。现在的解决方案是String(…),正如其他答案之一所示:

print(String(City.Chelyabinsk)) // prints out Cheylabinsk

答案 6 :(得分:4)

我碰到了这个问题,想分享一种简单的方法来创建提到的magicFunction

enum City: Int {
  case Melbourne = 1, Chelyabinsk, Bursa

    func magicFunction() -> String {
        return "\(self)"
    }
}

let city = City.Melbourne
city.magicFunction() //prints Melbourne

答案 7 :(得分:3)

对于swift:

extension UIDeviceBatteryState: CustomStringConvertible {
    public var description: String {
        switch self {
        case .unknown:
            return "unknown"
        case .unplugged:
            return "unplugged"
        case .charging:
            return "charging"
        case .full:
            return "full"
        }
    }
}

如果你的变量" batteryState"然后致电:

self.batteryState.description

答案 8 :(得分:2)

简单但有效...

enum ViewType : Int {
    case    Title
    case    Buttons
    case    View
}

func printEnumValue(enum: ViewType) {

    switch enum {
    case .Title: println("ViewType.Title")
    case .Buttons: println("ViewType.Buttons")
    case .View: println("ViewType.View")
    }
}

答案 9 :(得分:2)

斯威夫特现在拥有所谓的Implicitly Assigned Raw Value。基本上,如果你不为每种情况提供原始值并且枚举是String类型,它会推断出case的原始值本身是字符串格式。继续尝试一下。

enum City: String {
  case Melbourne, Chelyabinsk, Bursa
}

let city = City.Melbourne.rawValue

// city is "Melbourne"

答案 10 :(得分:0)

String(describing:)初始化程序可用于返回大小写标签名称,即使对于具有非String rawValues的枚举也是如此:

enum Numbers: Int {
    case one = 1
    case two = 2
}

let one = String(describing: Numbers.one) // "one"
let two = String(describing: Numbers.two) // "two"

请注意,如果枚举使用@objc修饰符,则不会起作用:

https://forums.swift.org/t/why-is-an-enum-returning-enumname-rather-than-caselabel-for-string-describing/27327

答案 11 :(得分:0)

Swift枚举中的自省功能部分起作用。

我看到@drewag的响应,发现一个没有rawValues的枚举确实可以在带有Xcode 11.5的Swift 5.X中进行自省。该代码有效。

public enum Domain: String {
    case network
    case data
    case service
    case sync
    var description: String {
        return "\(self)"     // THIS INTROSPECTION WORKS
    }
}
enum ErrorCode: Int, CustomStringConvertible {
    case success = 200
    case created = 201
    case accepted = 202
    case badRequest = 400
    case unauthorized = 401
    case forbidden = 403
    case notFound = 404
    var code: Int {
        return self.rawValue
    }
    var description: String {
        return "\(self)"      //THIS DOES NOT WORK - EXEC_BAD_ACCESS
    }
}
let errorCode = ErrorCode.notFound
let domain = Domain.network
print(domain.description, errorCode.code, errorCode.description)

在第二个"\(self)"中将"string"的{​​{1}}替换为Enum,您将获得以下打印输出: 网络404字符串

注意:使用String(self)代替"\(self)" in the first Enum will require the Enum to conform to the LosslessStringConvertible`协议,并添加其他初始化程序,因此字符串插值似乎是一个不错的解决方法。

要将var description: String添加到枚举,您将必须使用Switch语句将所有枚举大小写如前所述

var description: String {
    switch self {
    case .success: return "Success"
    case .created: return "Created"
    case .accepted: return "Accepted"
    }
}