回答:
Xcode 7ベータ5(Swiftバージョン2)以降では、デフォルトでを使用して型名と列挙型のケースを出力しprint(_:)
たり、の初期化子または文字列補間構文をString
使用して変換したりできます。だからあなたの例では: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"
これらの各シナリオで印刷される内容をカスタマイズできることに注意してください。
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)"
(私は、例えば、switch文に戻って頼ることなく、「都市メルボルンで」印刷する。使用して、この「デフォルト」の値に呼び出しへの道を発見していない\(self)
の実装にdescription
/ debugDescription
無限の再帰が発生します。)
上記のコメントString
のinit(_:)
&init(reflecting:)
イニシャライザは、に反映どのタイプの適合に応じて、印刷されるまさに説明します。
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)
}
この変更に関する情報について
は、リリースノートを参照してください。
CLAuthorizationStatus
内に(Objective C)列挙型の値を出力するなど、Swift以外の列挙型でこれを行う必要がある場合locationManager didChangeAuthorizationStatus
は、プロトコル拡張を定義する必要があります。次に例を示しextension CLAuthorizationStatus: CustomStringConvertable { public var description: String { switch self { case .AuthorizedAlways: return "AuthorizedAlways" <etc> } } }
ます。-これを実行すると、期待どおりに機能するはずです:print( "Auth status:(\ status))"。
現時点では、列挙型のケースに関する内省はありません。それぞれを手動で宣言する必要があります。
enum City: String, CustomStringConvertible {
case Melbourne = "Melbourne"
case Chelyabinsk = "Chelyabinsk"
case Bursa = "Bursa"
var description: String {
get {
return self.rawValue
}
}
}
生の型をIntにする必要がある場合は、自分で切り替えを行う必要があります。
enum City: Int, CustomStringConvertible {
case Melbourne = 1, Chelyabinsk, Bursa
var description: String {
get {
switch self {
case .Melbourne:
return "Melbourne"
case .Chelyabinsk:
return "Chelyabinsk"
case .Bursa:
return "Bursa"
}
}
}
}
get { ... }
セッターを定義しない場合は、簡潔にするためにこの部分を省略できます。
enum City : String, CustomStringConvertible {
です。上の最初のコード例では、最初の行をに変更します。次に、CSCプロトコルの一部として、プロパティをpublicに変更する必要があります。例:public var description : String {
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) }
}
その後、それをenumインスタンスの通常のメソッド呼び出しとして使用できます。以前の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列挙型でのみ機能します。
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)
String(describing:)
初期化子がさえ非文字列rawValuesと列挙型のためのcaseラベル名を返すために使用することができます。
enum Numbers: Int {
case one = 1
case two = 2
}
let one = String(describing: Numbers.one) // "one"
let two = String(describing: Numbers.two) // "two"
enumが修飾子を使用している場合、これは機能しないことに注意してください@objc
。
Objective-Cタイプ用に生成されたSwiftインターフェースには、@objc
修飾子が含まれていない場合があります。これらの列挙型はObjective-Cで定義されているため、上記のように機能しません。
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(…)
、他の回答の1つで提案されているように、現時点での解決策はです。
print(String(City.Chelyabinsk)) // prints out Cheylabinsk
var label:String { let mirror = Mirror(reflecting: self); if let label = mirror.children.first?.label { return label } else { return String(describing:self) } }
これはとても残念です。
それらの名前が必要な場合(コンパイラは正確なスペルを完全に知っているが、アクセスを許可しない-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
、コンパイラーは記憶喪失症であり、コンテキストを単独で呼び出すことができないため、いわゆる変数は、それらを囲む型の名前でスコープ修飾する必要があることに注意してください...
Swiftチームは本当に指揮をとらなければなりません。彼らはあなたができない列挙型を作成し、enumerate
使用できるものenumerate
は「シーケンス」ですが、ではありませんenum
!
Swiftには、Implicitly Assigned Raw Valueと呼ばれるものがあります。基本的に、各ケースに未加工の値を指定せず、列挙型がString型である場合、ケースの未加工の値自体が文字列形式であると推定されます。試してみてください。
enum City: String {
case Melbourne, Chelyabinsk, Bursa
}
let city = City.Melbourne.rawValue
// city is "Melbourne"
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
print(enum)
使用せずに文字列値が必要な場合は使用できますString(enum)