enumStringEnum: String{
case one = "one"case two = "two"case three = "three"
}
let anEnum = StringEnum(rawValue: "one")!
print("anEnum = \"\(anEnum.rawValue)\"")
Uwaga: nie musisz wpisywać = "jeden" itp. Po każdym przypadku. Domyślne wartości ciągów są takie same jak nazwy przypadków, więc wywołanie .rawValuezwróci tylko ciąg
EDYTOWAĆ
Jeśli chcesz, aby wartość ciągu zawierała takie rzeczy, jak spacje, które nie są poprawne jako część wartości wielkości liter, musisz jawnie ustawić ciąg. Więc,
enumStringEnum: String{
case one
case two
case three
}
let anEnum = StringEnum.one
print("anEnum = \"\(anEnum)\"")
daje
anEnum = "jeden"
Ale jeśli chcesz caseonewyświetlić „wartość 1”, musisz podać wartości ciągu:
enumStringEnum: String{
case one = "value one"case two = "value two"case three = "value three"
}
Wartość surowa musi być dosłownie zamienialna. Nie możesz użyć dowolnego Hashabletypu.
Vatsal Manot
1
Ok ... zacytowałem dokumentację Apple, która zawiera listę typów wartości, których można użyć jako wyliczeń surowych wartości. Ciągi znaków, pytanie OP, są jednym z obsługiwanych typów.
Duncan C
1
Hmm, wyobraź sobie case one = "uno". Teraz, jak przeanalizować "one"wartość wyliczenia? (nie można używać
surowych plików
Może mógłbyś zainicjować nieprzetworzony ciąg znaków podczas inicjalizacji, w zależności od lokalizacji ... lub po prostu mieć różne wyliczenia dla różnych lokalizacji. W każdym razie celem wyliczenia jest wyodrębnienie podstawowego surowca, tj. Lokalizacji. Dobry projekt kodu nie przekazywałby „uno” jako parametru w dowolnym miejscu, ale polegałby na StringEnum.one
SkyWalker
5
Nie musisz pisać = "one"itp. Po każdej sprawie. Domyślne wartości ciągów są takie same jak nazwy przypadków.
emlai
38
Wszystko czego potrzebujesz to:
enumFoo: String{
case a, b, c, d
}
let a = Foo(rawValue: "a")
assert(a == Foo.a)
let 💩 = Foo(rawValue: "💩")
assert(💩 == nil)
To nie jest technicznie właściwa odpowiedź, ponieważ sprawdza wartość surową. W podanym przykładzie nie określono wartości surowej, więc jest ona niejawnie dopasowywana do nazwy sprawy, ale jeśli masz wyliczenie z wartością surową, to się zepsuje.
Mark A. Donohoe
30
W Swift 4.2 protokół CaseIterable może być używany do wyliczenia z rawValues, ale ciąg powinien pasować do etykiet wyliczeniowych wielkości liter:
enumMyCode : String, CaseIterable{
case one = "uno"case two = "dos"case three = "tres"staticfuncwithLabel(_ label: String) -> MyCode? {
returnself.allCases.first{ "\($0)" == label }
}
}
To szalone, że nie można po prostu używać podobnej funkcji wbudowanej w język. Mogę sobie wyobrazić, że przechowujesz wartości w JSON, na przykład według nazwy wyliczenia, a następnie podczas analizowania musisz je przekonwertować. Pisanie enumFromStringmetody dla każdego używanego wyliczenia wydaje się szalone.
@Hemang Działa dobrze, w porządku, ale lepszym rozwiązaniem byłoby szybkie wsparcie dla automatycznego robienia tego. Szaleństwem jest robienie tego ręcznie dla każdego wyliczenia. Ale tak, to działa.
Peterdk
@Peterdk, czy możesz dodać osobną odpowiedź na to samo? Z pewnością pomogłoby to wszystkim tutaj.
Hemang
1
Nie jest szalone, że Swift nie obsługuje go natywnie. Szalone jest to, że funkcjonalność zależy od nazwy typu. Gdy wartość się zmieni, będziesz musiał refaktoryzować i zmieniać nazwy wszystkich zastosowań. To nie jest właściwy sposób rozwiązania tego problemu.
enumChassis: CaseIterable{
case pieridae, oovidae
}
let chassis: Chassis = Chassis.from(string: "oovidae")!
let string: String = chassis.toString()
Uwaga: to niestety nie zadziała, jeśli wyliczenie zostanie zadeklarowane jako @objc. O ile wiem, w Swift 5.3 nie ma sposobu, aby to działało z enum @objc, z wyjątkiem rozwiązań brutalnej siły (instrukcja przełączania).
Gdyby ktoś wiedział, jak sprawić, by to zadziałało dla wyliczeń @objc, byłabym bardzo zainteresowana odpowiedzią.
Odpowiedzi:
Pewnie. Wyliczenia mogą mieć wartość surową. Cytując dokumenty:
Możesz więc użyć takiego kodu:
enum StringEnum: String { case one = "one" case two = "two" case three = "three" } let anEnum = StringEnum(rawValue: "one")! print("anEnum = \"\(anEnum.rawValue)\"")
Uwaga: nie musisz wpisywać = "jeden" itp. Po każdym przypadku. Domyślne wartości ciągów są takie same jak nazwy przypadków, więc wywołanie
.rawValue
zwróci tylko ciągEDYTOWAĆ
Jeśli chcesz, aby wartość ciągu zawierała takie rzeczy, jak spacje, które nie są poprawne jako część wartości wielkości liter, musisz jawnie ustawić ciąg. Więc,
enum StringEnum: String { case one case two case three } let anEnum = StringEnum.one print("anEnum = \"\(anEnum)\"")
daje
Ale jeśli chcesz
case
one
wyświetlić „wartość 1”, musisz podać wartości ciągu:enum StringEnum: String { case one = "value one" case two = "value two" case three = "value three" }
źródło
Hashable
typu.case one = "uno"
. Teraz, jak przeanalizować"one"
wartość wyliczenia? (nie można używać= "one"
itp. Po każdej sprawie. Domyślne wartości ciągów są takie same jak nazwy przypadków.Wszystko czego potrzebujesz to:
enum Foo: String { case a, b, c, d } let a = Foo(rawValue: "a") assert(a == Foo.a) let 💩 = Foo(rawValue: "💩") assert(💩 == nil)
źródło
W Swift 4.2 protokół CaseIterable może być używany do wyliczenia z rawValues, ale ciąg powinien pasować do etykiet wyliczeniowych wielkości liter:
enum MyCode : String, CaseIterable { case one = "uno" case two = "dos" case three = "tres" static func withLabel(_ label: String) -> MyCode? { return self.allCases.first{ "\($0)" == label } } }
stosowanie:
print(MyCode.withLabel("one")) // Optional(MyCode.one) print(MyCode(rawValue: "uno")) // Optional(MyCode.one)
źródło
W przypadku wyliczenia typu Int możesz to zrobić tak:
enum MenuItem: Int { case One = 0, Two, Three, Four, Five //... as much as needs static func enumFromString(string:String) -> MenuItem? { var i = 0 while let item = MenuItem(rawValue: i) { if String(item) == string { return item } i += 1 } return nil } }
I użyć:
let string = "Two" if let item = MenuItem.enumFromString(string) { //in this case item = 1 //your code }
źródło
enumFromString
metody dla każdego używanego wyliczenia wydaje się szalone.Rozszerzam odpowiedź Duncana C.
extension StringEnum: StringLiteralConvertible { init(stringLiteral value: String){ self.init(rawValue: value)! } init(extendedGraphemeClusterLiteral value: String) { self.init(stringLiteral: value) } init(unicodeScalarLiteral value: String) { self.init(stringLiteral: value) } }
źródło
Swift 4.2:
public enum PaymentPlatform: String, CaseIterable { case visa = "Visa card" case masterCard = "Master card" case cod = "Cod" var nameEnum: String { return Mirror(reflecting: self).children.first?.label ?? String(describing: self) } func byName(name: String) -> PaymentPlatform { return PaymentPlatform.allCases.first(where: {$0.nameEnum.elementsEqual(name)}) ?? .cod } }
źródło
W przypadku wyliczenia Int i ich reprezentacji typu String deklaruję wyliczenie w następujący sposób:
enum OrderState: Int16, CustomStringConvertible { case waiting = 1 case inKitchen = 2 case ready = 3 var description: String { switch self { case .waiting: return "Waiting" case .inKitchen: return "InKitchen" case .ready: return "Ready" } } static func initialize(stringValue: String)-> OrderState? { switch stringValue { case OrderState.waiting.description: return OrderState.waiting case OrderState.inKitchen.description: return OrderState.inKitchen case OrderState.ready.description: return OrderState.ready default: return nil } } }
Stosowanie:
order.orderState = OrderState.waiting.rawValue let orderState = OrderState.init(rawValue: order.orderState) let orderStateStr = orderState?.description ?? "" print("orderStateStr = \(orderStateStr)")
źródło
Riffowanie na odpowiedź djruss70, aby stworzyć wysoce uogólnione rozwiązanie:
extension CaseIterable { static func from(string: String) -> Self? { return Self.allCases.first { string == "\($0)" } } func toString() -> String { "\(self)" } }
Stosowanie:
enum Chassis: CaseIterable { case pieridae, oovidae } let chassis: Chassis = Chassis.from(string: "oovidae")! let string: String = chassis.toString()
Uwaga: to niestety nie zadziała, jeśli wyliczenie zostanie zadeklarowane jako @objc. O ile wiem, w Swift 5.3 nie ma sposobu, aby to działało z enum @objc, z wyjątkiem rozwiązań brutalnej siły (instrukcja przełączania).
Gdyby ktoś wiedział, jak sprawić, by to zadziałało dla wyliczeń @objc, byłabym bardzo zainteresowana odpowiedzią.
źródło