2017-07-26 6 views
0

異なる列挙型を同じ変数に渡し、その型を後で識別し、生の値を使用していくつかの操作を行うにはどうすればよいですか?Swift - 同じ変数の異なる列挙型をクラスに渡す

String型の2つの列挙型Menu1およびMenu2があります。列挙型の配列を別のクラスに渡してサブメニューを表示するのが好きです。私は将来別のメニューを追加するかもしれないので、同じ変数にenumを渡すのが好きです。

+0

2つの列挙型を組み合わせて単一の列挙型にすることはできませんか? – Priyal

+0

'Any'が助けになるかもしれませんが、' enum'型にキャストする必要があります。 – Lawliet

+0

いいえ。列挙型の値が高いので、別々にしておきたい。 – prabhu

答えて

1

次のように抽象化を適用するために、あなたは、を使用することができます。

protocol Menu {} 

enum Menu1: String, Menu { 
    case option1 = "Option 01 From Menu 01" 
    case option2 = "Option 02 From Menu 01" 
    case option3 = "Option 03 From Menu 01" 
    case option4 = "Option 04 From Menu 01" 
    case option5 = "Option 05 From Menu 01" 
} 

enum Menu2: String, Menu { 
    case option1 = "Option 01 From Menu 02" 
    case option2 = "Option 02 From Menu 02" 
    case option3 = "Option 03 From Menu 02" 
    case option4 = "Option 04 From Menu 02" 
    case option5 = "Option 05 From Menu 02" 
} 

これを実装することにより、あなたが列挙型の両方を含んでMenu型の配列を宣言することができます:

let myMenu1Array: [Menu1] = [.option1, .option2, .option5] 
let myMenu2Array: [Menu2] = [.option1, .option3, .option4] 

たとえば、配列をMenuとする関数は、次のように動作します。

func handleMenu(_ menuArray: [Menu]) { 
    if let menu1Array = menuArray as? [Menu1] { 
     print("Menu 1 Detected!") 

     // you could iterate through it for instance... 
     for option in menu1Array { 
      print(option.rawValue) 
     } 

     return 
    } 

    if let menu2Array = menuArray as? [Menu2] { 
     print("Menu 2 Detected!") 

     // you could iterate through it for instance... 
     for option in menu2Array { 
      print(option.rawValue) 
     } 

     return 
    } 
} 

出力は次のようになります。だから、

handleMenu(myMenu1Array) 
/* 
Menu 1 Detected! 
Option 01 From Menu 01 
Option 02 From Menu 01 
Option 05 From Menu 01 
*/ 

handleMenu(myMenu2Array) 
/* 
Menu 2 Detected! 
Option 01 From Menu 02 
Option 03 From Menu 02 
Option 04 From Menu 02 
*/ 

、あなたはメニューを表し、あなたがMenuの種類としてそれを宣言することができなければならないクラスのプロパティがある場合:

class MyClass { 
    ... 

    var menu: Menu? 

    ... 
} 
+0

'is'ではなく'条件付きバインディング 'を使用するべきです( 'menu1をmenuArrayとして[メニュー1] ...')' – Alexander

+0

ああ、なんて愚かな間違い! @アレキサンダーノートのおかげで:)編集されました。 –

1

2つの列挙型に準拠する必要があるプロトコルを1つ宣言できます。 プロトコルに確定した関数パラメータを受け入れます。あるいは、ジェネリックを利用することもできます。

+0

上記の可能性の例を示すことができれば助けになるだろう。私は即座に新しく、enumに関するジェネリックとプロトコルについてよく分かりません – prabhu

1

を2つの列挙型を接続する方法が必要です。共通のMenuプロトコルである可能性があります。あなたが直面する問題は、Menuオブジェクトを通過させる際の型の消去です。新しいメニュータイプを追加するのは簡単ではなく、コード内のどこからでもチェックするのは簡単です。

私は小さなリファクタを提案し、それぞれを別の列挙型にラップし、共通の構造体で管理します。この方法に

enum Menu1: String { 
    case option1 = "Option 01 From Menu 01" 
    case option2 = "Option 02 From Menu 01" 
    case option3 = "Option 03 From Menu 01" 
    case option4 = "Option 04 From Menu 01" 
    case option5 = "Option 05 From Menu 01" 
} 

enum Menu2: String { 
    case option1 = "Option 01 From Menu 02" 
    case option2 = "Option 02 From Menu 02" 
    case option3 = "Option 03 From Menu 02" 
    case option4 = "Option 04 From Menu 02" 
    case option5 = "Option 05 From Menu 02" 
} 

struct Menu 
{ 
    enum MenuType 
    { 
     case one (Menu1) 
     case two (Menu2) 
    } 

    let type: MenuType 
} 


func handle(menu: Menu) 
{ 
    switch menu.type 
    { 
    case .one(let data): print (data.rawValue) 
    case .two(let data): print (data.rawValue) 
    } 
} 

let menu = Menu(type: .one(Menu1.option1)) 
handle(menu: menu) 

重要な利点:

  1. あなたが任意のメニュー
  2. あなたが新しいメニューの種類を追加し、任意の時間を追加し続けることができ、あなたのコード内のすべてのswitch文は、コンパイルにキックされますあなたのコードを更新する必要がある場所を示す
  3. 新しいメニューの関連するデータ型は何でも構いません(構造体、イメージ、入れ子サブメニューなど)
  4. オプションはありません - onlコンクリートタイプ
関連する問題