Jak uzyskać nazwę wartości wyliczenia w języku Swift?
Jeśli mam wyliczenie z surowymi Integer
wartościami:
enum City: Int {
case Melbourne = 1, Chelyabinsk, Bursa
}
let city = City.Melbourne
Jak mogę przekonwertować wartość city
na łańcuch Melbourne
? Czy tego rodzaju introspekcja typu jest dostępna w danym języku?
Coś w stylu (ten kod nie zadziała):
println("Your city is \(city.magicFunction)")
> Your city is Melbourne
9 answers
Począwszy od Xcode 7 beta 5 możesz teraz domyślnie drukować nazwy typów i przypadki enum używając print(_:)
, lub przekonwertować na String
używając inicjatora String
lub składni interpolacji ciągu znaków. Więc dla Twojego przykładu:
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"
Nie ma więc potrzeby definiowania i utrzymywania wygodnej funkcji, która włącza każdy przypadek, aby zwrócić literalny łańcuch znaków. Ponadto działa to automatycznie dla każdego enum, nawet jeśli nie podano typu raw-value.
debugPrint(_:)
& String(reflecting:)
może być stosowany do nazwa w pełni kwalifikowana:
debugPrint(city)
// prints "App.City.Melbourne" (or similar, depending on the full scope)
let cityDebugName = String(reflecting: city)
// cityDebugName contains "App.City.Melbourne"
Zauważ, że możesz dostosować to, co jest drukowane w każdym z tych scenariuszy:
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)"
(nie znalazłem sposobu na wywołanie tej wartości "domyślnej", na przykład, aby wydrukować" miasto to Melbourne " bez uciekania się do instrukcji switch. Wykorzystanie \(self)
w realizacji description
/debugDescription
powoduje nieskończoną rekurencję.)
Komentarze powyżej String
' s init(_:)
& init(reflecting:)
inicjalizatory opisują dokładnie to, co jest drukowane, w zależności na czym odpowiada Typ refleksyjny:
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)
}
Informacje na temat tej zmiany można znaleźć w Uwagach do wydania .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-30 10:47:41
W tej chwili nie ma introspekcji na temat przypadków enum. Będziesz musiał zadeklarować każdy z nich ręcznie:
enum City : String, Printable {
case Melbourne = "Melbourne"
case Chelyabinsk = "Chelyabinsk"
case Bursa = "Bursa"
var description : String {
get {
return self.rawValue
}
}
}
Uwaga : protokół Printable
nie działa obecnie na placach zabaw. Jeśli chcesz zobaczyć ciąg znaków na placu zabaw, musisz ręcznie wywołać toRaw ()
Jeśli chcesz, aby surowy typ był Int, musisz zrobić przełącznik samodzielnie:
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"
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-27 16:08:11
W Swift - 3 (testowanym z XCode 8.1) możesz dodać następujące metody w swoim enum:
/**
* 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) }
}
Możesz użyć go jako normalnego wywołania metody na Twojej instancji enum. Może to również działać w poprzednich wersjach Swift, ale nie testowałem go.
W twoim przykładzie:
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"
Jeśli chcesz udostępnić tę funkcjonalność wszystkim swoim enumom, możesz zrobić z niej rozszerzenie:
/**
* 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) }
}
}
To działa tylko dla Swift enums.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 15:22:10
Dla Objective-C enum
S jedynym sposobem obecnie wydaje się na przykład rozszerzenie enum oCustomStringConvertible
zakończone czymś w rodzaju:
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"
}
}
}
A następnie rzuca enum
jako String
:
String(UIDevice.currentDevice().batteryState)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-02 14:15:21
To takie rozczarowujące.
W Przypadku, Gdy potrzebujesz tych nazw (które kompilator doskonale zna dokładną pisownię, ale odmawia dostępu -- dziękuję Swift team!! -jeśli nie chcesz lub nie możesz uczynić String bazą twojego enum, czasochłonna alternatywa jest następująca:
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()
}
}
}
Możesz użyć powyższego w następujący sposób:
let elementType = ViewType.Title
let column = Column.Collections
let row = 0
println("fetching element \(elementType), column: \(column.string()), row: \(row)")
I otrzymasz oczekiwany wynik (kod dla kolumny podobny, ale nie pokazany)
fetching element Title, column: Collections, row: 0
W powyższym, I sprawiły, że właściwość description
odnosi się z powrotem do metody string
, ale jest to kwestia gustu. Zauważ również, że tak zwane zmienne static
muszą być kwalifikowane przez nazwę ich typu, ponieważ kompilator jest zbyt amnezyjny i nie może sam przywołać kontekstu...
Drużyna Swift musi być naprawdę dowodzona. Stworzyli enum, którego nie można enumerate
i na którym można użyć enumerate
są "sekwencjami", ale nie enum
!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-24 13:51:26
Poza obsługą String (...) (CustomStringConvertible) dla enums w Swift 2.2, jest też nieco zepsuta obsługa odbicia dla nich. Dla przypadków enum z powiązanymi wartościami można uzyskać etykietę przypadku enum za pomocą odbicia:
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"
Mówiąc o złamaniu, miałem jednak na myśli, że dla" prostych " enum, powyższa właściwość obliczeniowa oparta na odbiciu label
zwraca po prostu nil
(boo-hoo).
print(City.Chelyabinsk.label) // prints out nil
Sytuacja z odbiciem powinna być coraz lepsza po Swift 3, najwyraźniej. Na razie jednak rozwiązaniem jest String(…)
, jak sugerowano w jednej z innych odpowiedzi:
print(String(City.Chelyabinsk)) // prints out Cheylabinsk
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-28 23:36:40
Proste, ale działa...
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")
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-09 11:04:41
Swift ma teraz coś, co jest znane jako domyślnie przypisana wartość raw . Zasadniczo, jeśli nie podasz wartości nieprzetworzonych dla każdego przypadku, a enum jest typu String, wywnioskujesz, że nieprzetworzona wartość sprawy jest sama w formacie string. Spróbuj.
enum City: String {
case Melbourne, Chelyabinsk, Bursa
}
let city = City.Melbourne.rawValue
// city is "Melbourne"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-02 14:41:30
Dla 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"
}
}
}
Jeśli twoja zmienna "batteryState" to wywołaj:
Self.batteryState.Opis
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-05 07:16:49