如何获得Swift中的枚举值的名称?
如果我有一个枚举Integer
原始值:
enum City: Int { case Melbourne = 1, Chelyabinsk, Bursa } let city = City.Melbourne
如何将city
值转换为stringMelbourne
? 这种types的名字反省在语言中可用吗?
像(这个代码不会工作):
println("Your city is \(city.magicFunction)") > Your city is Melbourne
从Xcode 7 beta 5开始,现在可以使用print(_:)
来打印types名称和枚举情况,或者使用String
的init(_:)
初始值设定项或string插值语法将其转换为String
。 所以对于你的例子:
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"
所以不再需要定义和维护一个方便的函数来打开每个case来返回一个string。 另外,即使没有指定原始值types,它也会自动适用于任何枚举。
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"
请注意,您可以自定义在以下每种情况下打印的内容:
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)"
(我还没有find调用这个“默认”值的方法,例如,打印“城市是墨尔本”,而不debugDescription
switch语句。在description
/ debugDescription
的实现中使用\(self)
会导致无限recursion)。
上面的注释String
的init(_:)
& init(reflecting:)
初始化符准确地描述了打印的内容,取决于reflectiontypes的符合情况:
extension String { /// Initialize `self` with the textual representation of `instance`. /// /// * If `T` conforms to `Streamable`, the result is obtained by /// calling `instance.writeTo(s)` on an empty string s. /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the /// result is `instance`'s `description` /// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`, /// the result is `instance`'s `debugDescription` /// * Otherwise, an unspecified result is supplied automatically by /// the Swift standard library. /// /// - SeeAlso: `String.init<T>(reflecting: T)` public init<T>(_ instance: T) /// Initialize `self` with a detailed textual representation of /// `subject`, suitable for debugging. /// /// * If `T` conforms to `CustomDebugStringConvertible`, the result /// is `subject`'s `debugDescription`. /// /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the result /// is `subject`'s `description`. /// /// * Otherwise, if `T` conforms to `Streamable`, the result is /// obtained by calling `subject.writeTo(s)` on an empty string s. /// /// * Otherwise, an unspecified result is supplied automatically by /// the Swift standard library. /// /// - SeeAlso: `String.init<T>(T)` public init<T>(reflecting subject: T) }
有关此更改的信息,请参阅发行说明 。
目前没有对枚举个案的反省。 您将不得不手动声明它们:
enum City : String, Printable { case Melbourne = "Melbourne" case Chelyabinsk = "Chelyabinsk" case Bursa = "Bursa" var description : String { get { return self.rawValue } } }
注意 : Printable
协议当前不在Playgrounds中工作。 如果你想在操场上看到string,你必须手动调用toRaw()
如果您需要原始types为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" } } } }
在Swift-3中(用XCode 8.1testing),你可以在你的枚举中添加下面的方法:
/** * 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版本中工作,但是我没有testing它。
在你的例子中:
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"
如果要为所有枚举提供此function,可以将其扩展为:
/** * 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枚举。
这太令人失望了。
对于你需要这些名字的情况(编译器完全知道拼写的确切内容,但是拒绝访问 – 谢谢你Swift团队!!)但是不想或者不能让String成为你枚举的基础,详细,繁琐的替代方法如下:
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
variables需要通过它们的封闭types的名称来限定范围,因为编译器太遗忘,并且不能单独回忆上下文…
Swift团队必须得到真正的指挥。 他们创build枚举,你不能enumerate
,你可以使用enumerate
是“序列”,而不是enum
!
对于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" } } }
然后以String
enum
:
String(UIDevice.currentDevice().batteryState)
简单,但工程…
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") } }
现在Swift具有被称为隐式赋值的原始值 。 基本上,如果您不给每个案例的原始值,并且枚举types为String,则会推断出案例的原始值本身是string格式。 继续尝试。
enum City: String { case Melbourne, Chelyabinsk, Bursa } let city = City.Melbourne.rawValue // city is "Melbourne"
在Swift 2.2中对于enums的String(…)(CustomStringConvertible)支持之外,对它们也有一些破坏的reflection支持。 对于具有相关值的枚举案例,可以使用reflection来获取枚举案例的标签:
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"
然而,通过破解,我意味着对于“简单的”枚举,上面的基于reflection的label
计算属性只返回nil
(boo-hoo)。
print(City.Chelyabinsk.label) // prints out nil
Swift 3之后的反思情况应该会越来越好,显然。 现在的解决scheme是String(…)
,正如其他答案中的build议:
print(String(City.Chelyabinsk)) // prints out Cheylabinsk