2017-12-14 4 views
0

この列挙を考える(そのタイプはIntであることに注意)はあなたがそれの名前から列挙型の値を初期化することができるケースです(*ない*そのRawValue?)

enum MyTestEnum : Int{ 
    case one  = 1 
    case eight = 8 
    case unknown = -1 
} 

あなたは簡単に基づいて、このバージョンを初期化することができます生の値、そう...

let value = MyTestEnum(rawValue:-1) 

のように私は 'の後、それはケース名自体(再び、ない生の値の文字列表現で初期化することが可能かどうかを確認しようとしているが、言葉ですケース 'など)...

let value = MyTestEnum(caseName:"eight") 

注:可能であれば、生の値の型にかかわらず、これはの任意の enumで動作します。例えば、これは...

enum MyOtherEnum{ 
    case xxx 
    case yyy 
    case zzz 
} 

let value = MyOtherEnum(caseName:"xxx") 

これはできますか?

思考:

  • 私はスウィフトは、完全修飾クラス名を表す文字列指定されたクラスをインスタンス化する方法があると思います。おそらく類似のものがここで使用できます。
+0

JSON(de)seriailationの目的ですか? – Alexander

+0

いいえ、それは一般的な目的です(私たちは他の言語では問題なし)。しかし、これを試している特定のユースケースは、Xcode拡張を記述し、列挙のケース名をコマンドIDとし、文字列rawValueラベルにする。ユーザーからコマンドを取得したら、コマンドIDを取得するので、スイッチで使用できるようにケースを再作成しようとしています。 – MarqueIV

+0

'String'のrawValueを使用していない理由はありますか? 8、2、-1、...が必要ですか? – Alexander

答えて

0

それは生IntString値を持っているあなたの希望のようなあなたの列挙例が鳴ります。これは、これを行うには厳密には不可能ですが、おそらくこれは近づく:

enum MyTestEnum : String { 
    case one 
    case eight 
    case unknown 

    var intValue: Int { 
     switch self { 
     case one: return 1 
     case eight: return 8 
     case unknown: return -1 
     } 
    } 
} 

今、あなたはケース名から初期化することができますが、必要なときに、あなたはまた、intValueを取得することができます。 (必要に応じて、あなたは簡単にも整数から初期化を許可するようにfailable初期化子を追加することもできます。)

+0

生の価値に言及することで、私は混乱していると思う。一緒に忘れてください。再度、私は文字列 "eight"からMyTestEnum.eightのインスタンスを作成しようとしています。理にかなっている? – MarqueIV

+0

はい、この解決策があります。整数の生の値が必要ない場合は、単に 'intValue'の計算されたプロパティをそのままにしておいてください。単純に 'String'の生の値を持つと自動的にあなたの名前を名前で初期化することができます。 – andyvn22

+0

(あなたの質問が「名前で列挙型を初期化できますか?文字列の生の値を与えないで*できますか?」という答えは「Nope、あなたが自分でイニシャライザを書いていない限りはありません」) – andyvn22

1

をあなたはカスタム初期化子手動

extension MyTestEnum { 
    public static func allValues() -> [MyTestEnum] { 
     let retVal = AnySequence {() -> AnyIterator<MyTestEnum> in 
      var raw = 0 
      return AnyIterator { 
       let current = withUnsafePointer(to: &raw) { 
        $0.withMemoryRebound(to: MyTestEnum.self, capacity: 1) { $0.pointee } 
       } 
       guard current.hashValue == raw else { return nil } 
       raw += 1 
       return current 
      } 
     } 

     return [MyTestEnum](retVal) 
    } 

    init?(caseName: String){ 
     for v in MyTestEnum.allValues() { 
      if "\(v)" == caseName { 
       self = v 
       return 
      } 
     } 
     self = MyTestEnum.unknown 
    } 
} 

let test = MyTestEnum(caseName: "eight") 

または単純にすべてのあなたのケースを行くことができます:)

extension MyTestEnum { 
init?(caseName: String){ 
    switch caseName { 
    case "eight": self.init(rawValue: 8) 
    case "one": self.init(rawValue: 1) 
    default: self.init(rawValue: -1) 
    } 
} 
} 

let test1 = MyTestEnum(caseName: "eight") 
let test2 = MyTestEnum(rawValue: 1) 

これが役立つことを願っています!

+0

私は 'self = .eight'、' self = .one'などを使用します。生の値への接続は混乱します(実際の値の後に名前が付けられていない列挙体の場合) – Alexander

+0

これは実際には解決しません私たちの問題。問題は文字列から初期化するだけでなく、既存の名前から初期化することです。これで、init文の中でリストを維持する必要があります。 (副作用として、あなたは既に値を直接指定することができるので、手作業で行っているので、未処理の値を持つinit呼び出しは必要ありません) – MarqueIV

+0

@Alexander wow、本当に??? initメソッドでself = .eightを使用することはできません。私はswift 4を使用しています。どのバージョンのswiftを使用していますか? –

関連する問題