Jeśli mam wyliczenie ze przypadkami a, b, c, d, czy mogę rzucić ciąg „a” jako wyliczenie?
Odpowiedzi:
Pewnie. Wyliczenia mogą mieć wartość surową. Cytując dokumenty:
Nieprzetworzone wartości mogą być łańcuchami, znakami lub dowolnym typem liczb całkowitych lub zmiennoprzecinkowych
- Fragment od: Apple Inc. „Swift Programming Language”. iBooks. https://itun.es/us/jEUH0.l ,
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 .rawValuezwróci tylko ciąg
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
anEnum = "jeden"
Ale jeśli chcesz case onewyświetlić „wartość 1”, musisz podać wartości ciągu:
enum StringEnum: String
{
case one = "value one"
case two = "value two"
case three = "value three"
}
Hashabletypu.
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)
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)
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
}
enumFromStringmetody 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)
}
}
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
}
}
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)")
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ą.