स्विफ्ट में, क्या स्ट्रिंग को एनम में बदलना संभव है?


93

अगर मेरे पास मामलों के साथ एक एनम है, तो बी, सी, डी क्या मेरे लिए स्ट्रिंग "ए" को एनम के रूप में डालना संभव है?


3
इन 'जातियों' को शाब्दिक रूपांतरण कहा जाता है।
वत्सल मनोट

जवाबों:


136

ज़रूर। एनम का कच्चा मान हो सकता है। डॉक्स को उद्धृत करने के लिए:

कच्चे मूल्य तार, वर्ण या पूर्णांक या फ्लोटिंग-पॉइंट संख्या प्रकारों में से कोई भी हो सकते हैं

- अंश: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।" iBooks। https://itun.es/us/jEUH0.l ,

तो आप इस तरह कोड का उपयोग कर सकते हैं:

enum StringEnum: String 
{
  case one = "one"
  case two = "two"
  case three = "three"
}

let anEnum = StringEnum(rawValue: "one")!

print("anEnum = \"\(anEnum.rawValue)\"")

नोट: आपको प्रत्येक मामले के बाद = "एक" आदि लिखने की आवश्यकता नहीं है। डिफ़ॉल्ट स्ट्रिंग मान समान होते हैं, इसलिए कॉल करने वाले नाम .rawValueकेवल एक स्ट्रिंग लौटाएंगे

संपादित करें

यदि आपको स्ट्रिंग मान की आवश्यकता होती है जिसमें रिक्त स्थान जैसी चीजें शामिल हैं जो केस वैल्यू के हिस्से के रूप में मान्य नहीं हैं तो आपको स्ट्रिंग को स्पष्ट रूप से सेट करने की आवश्यकता है। इसलिए,

enum StringEnum: String 
{
  case one
  case two
  case three
}

let anEnum = StringEnum.one
print("anEnum = \"\(anEnum)\"")

देता है

एन्नुम = "एक"

लेकिन अगर आप case one"मूल्य एक" प्रदर्शित करना चाहते हैं, तो आपको स्ट्रिंग मान प्रदान करने की आवश्यकता होगी:

enum StringEnum: String 
{
  case one   = "value one"
  case two   = "value two"
  case three = "value three"
}

कच्चे मूल्य को शाब्दिक रूप से परिवर्तनीय होना चाहिए। आप किसी भी Hashableप्रकार का उपयोग नहीं कर सकते ।
वत्सल मनोट

1
ठीक है ... मैंने Apple डॉक्स को उद्धृत किया है, जो उन मूल्यों के प्रकारों को सूचीबद्ध करता है जिन्हें एनम कच्चे मूल्यों के रूप में इस्तेमाल किया जा सकता है। स्ट्रिंग्स, ओपी का प्रश्न, समर्थित प्रकारों में से एक है।
डंकन सी

1
हम्म, कल्पना case one = "uno"। अब, "one"वैल्यू टू एन्यूम कैसे करें ? (कच्चे का उपयोग नहीं कर सकते, क्योंकि वे स्थानीयकरण के लिए उपयोग किए जाते हैं)
Agent_L

हो सकता है कि आप स्थानीयकरण के आधार पर कच्ची स्ट्रिंग को इनिशियलाइज़ कर सकें ... या बस अलग-अलग लोकलाइज़ेशन के लिए अलग-अलग एनम लें। किसी भी मामले में एक एनुम होने का पूरा उद्देश्य अंतर्निहित कच्चे यानी स्थानीयकरण को समाप्त करना है। एक अच्छा कोड डिज़ाइन पैरामीटर के रूप में कहीं भी "अनओ" को पारित नहीं करेगा, लेकिन StringEnum.one पर निर्भर करेगा
SkyWalker

5
आपको = "one"प्रत्येक मामले के बाद लिखने आदि की आवश्यकता नहीं है । डिफ़ॉल्ट स्ट्रिंग मान केस नामों के समान होते हैं।
इमली

38

जो तुम्हे चाहिए वो है:

enum Foo: String {
   case a, b, c, d
}

let a = Foo(rawValue: "a")
assert(a == Foo.a)

let 💩 = Foo(rawValue: "💩")
assert(💩 == nil)

यह तकनीकी रूप से सही उत्तर नहीं है क्योंकि यह कच्चे मूल्य की जाँच करता है। यहां दिए गए उदाहरण के अनुसार, कोई कच्चा मान निर्दिष्ट नहीं किया गया है, इसलिए इसका संक्षेप में मामला नाम से मेल खाता है, लेकिन यदि आपके पास कच्चे मान के साथ एक एनम है, तो यह टूट जाता है।
मार्क ए। डोनोहे

26

स्विफ्ट 4.2 में, CaseIterable प्रोटोकॉल का उपयोग कच्चे माल के साथ एक एनम के लिए किया जा सकता है, लेकिन स्ट्रिंग को एनम केस लेबल के साथ मेल खाना चाहिए:

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 }
    }
}

उपयोग:

print(MyCode.withLabel("one")) // Optional(MyCode.one)
print(MyCode(rawValue: "uno"))  // Optional(MyCode.one)

2
यह एक महान जवाब है! यह वास्तव में प्रश्न को संबोधित करता है।
मैट रूंडले

3
यह एकमात्र उत्तर है जो वास्तव में ओपी द्वारा पूछे गए कार्यों के रूप में काम करता है, जो कि मामले में कच्चे मूल्यों के नाम नहीं था । अच्छा उत्तर!
मार्क ए। डोनोहे

1
जबकि यह काम करता है, इसकी बहुत मूर्खतापूर्ण बात है। कृपया कोड में मामलों के नामों पर आधार कार्यक्षमता न करें।
सुल्तान

7
वह और क्या करने वाला है? क्या होगा यदि वह एक डेटाबेस में एक एनम लिख रहा है और फिर उसे वापस लाने की आवश्यकता है?
जो

15

इंट के प्रकार के साथ एक एनुम के मामले में आप ऐसा कर सकते हैं:

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
    }
}

और उपयोग करें:

let string = "Two"
if let item = MenuItem.enumFromString(string) {
    //in this case item = 1 
    //your code
} 

1
यह पागल है कि आप भाषा में समान कार्यक्षमता बिलिन का उपयोग नहीं कर सकते। मैं कल्पना कर सकता हूं कि आप JSON में मानों को एनम नाम से स्टोर कर सकते हैं, और फिर पार्सिंग पर उन्हें वापस बदलने की आवश्यकता है। enumFromStringआपके द्वारा उपयोग किए जाने वाले प्रत्येक एनम के लिए एक विधि लिखना पागल लगता है।
पीटरडक

1
@Peterdk, कृपया सर्वोत्तम संभव विकल्प का सुझाव दें। इगोर समाधान वास्तव में सिर्फ मेरे लिए काम किया।
हेमंग

@ हेमांग यह ठीक काम करता है, ठीक है, लेकिन एक बेहतर समाधान स्वचालित रूप से ऐसा करने के लिए स्विफ्ट समर्थन होगा। यह प्रत्येक एनम के लिए मैन्युअल रूप से ऐसा करने के लिए पागल है। लेकिन हां, यह काम करता है।
पीटरडक

@Peterdk, क्या आप कृपया उसी के लिए एक अलग उत्तर जोड़ सकते हैं? यह निश्चित रूप से हर किसी को यहाँ मदद करेगा।
हेमांग

1
यह पागल नहीं है कि स्विफ्ट मूल रूप से इसका समर्थन नहीं करता है। पागल बात यह है कि कार्यक्षमता एक प्रकार के नाम पर निर्भर करती है। जब मूल्य बदल जाता है, तो आपको सभी प्रकार के रिफलेक्टर और नाम बदलने होंगे। इसे हल करने का यह सही तरीका नहीं है।
सुल्तान

2

डंकन सी के जवाब का विस्तार

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)
    }
}

2

स्विफ्ट 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
    }
}

1

इंट एनम और उनके स्ट्रिंग प्रतिनिधित्व के लिए, मैं एनम की घोषणा इस प्रकार करता हूं:

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
        }
    }
}

उपयोग:

order.orderState = OrderState.waiting.rawValue

let orderState = OrderState.init(rawValue: order.orderState)
let orderStateStr = orderState?.description ?? ""
print("orderStateStr = \(orderStateStr)")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.