2015-11-07 10 views
5

私がしようとしているのは、列挙から生の値の配列をフェッチするプロトコル拡張を作成することです。たとえば、私は次のことを持っていると言う:Swift enumからすべてのrawValuesを取得するためのプロトコル拡張を作成するには

enum TestType: String, EnumIteratable { 
    case unitTest = "Unit Test" 
    case uiTest = "UI Test" 
} 

class EnumIterator: NSObject { 
    class func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> { 
     var i = 0 
     return anyGenerator { 
      let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory } 
      return next.hashValue == i++ ? next : nil 
     } 
    } 

    class func getValues<T: Hashable>(_: T.Type) -> [T] { 
     let iterator = self.iterateEnum(T) 
     var returnArray = [T]() 
     for val in iterator { 
      returnArray.append(val) 
     } 
     return returnArray 
    } 

} 

どのように私はTestType.getRawValuesを呼び出すことができるように(プロトコルEnumIteratableを実装)と、それはすべての生列挙値の文字列配列を返すことができますか?

ありがとうございます!

+0

おそらくMirrorTypeを使用していますか? –

+0

@MarceloFabriミラーはいくつかの理由で機能しません。その1つは、実際には、私が避けようとしているenumのインスタンスが必要なことです。また、列挙型はプロパティを持っていません:) – JonahGabriel

答えて

1

静的プロパティを追加するだけで、すべての列挙型の値を返すことができます。たとえば、

enum RelationshipStatus: String { 

    case Single = "Single" 
    case Married = "Married" 
    case ItsComplicated = "It's complicated" 

    static let all: [RelationshipStatus] = [.Single, .Married, .ItsComplicated] 

} 

for status in RelationshipStatus.all { 
    print(status.rawValue) 
} 
+1

それは私が考えていたよりも簡単です。ありがとう! – JonahGabriel

2

Scottのソリューションは、おそらくあなたが望むものです。しかし、任意の将来の列挙に適用できるより汎用的なものを探していて、追加のケースを許すなら、これを試すことができます:

まず、Enumのケースを反復するメソッドが必要です。私はここから、この実装を使用:https://stackoverflow.com/a/28341290/914887

func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> { 
    var i = 0 
    return anyGenerator { 
     let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory } 
     return next.hashValue == i++ ? next : nil 
    } 
} 

次に、あなたが欲しい静的な関数を定義して、あなたのプロトコルを作成することができます。

protocol EnumIteratable { 
    typealias ENUM_TYPE:Hashable, RawRepresentable = Self 
    static func getAllValues() -> [ ENUM_TYPE ] 
    static func getRawValues() -> [ ENUM_TYPE.RawValue ] 
} 

私が適合列挙型を指定できるように関連付けられた型を使用しましたプロトコルの型。 getAllValuesは厳密には必要ではありませんが、ロジックを簡素化します。

その後、あなたは一般的なデフォルトの実装を定義することができます。

extension EnumIteratable { 
    static func getAllValues() -> [ ENUM_TYPE ] 
    { 
     var retval = [ ENUM_TYPE ]() 
     for item in iterateEnum(ENUM_TYPE) 
     { 
      retval.append(item) 
     } 
     return retval 
    } 

    static func getRawValues() -> [ ENUM_TYPE.RawValue ] 
    { 
     return getAllValues().map({ (item:ENUM_TYPE) -> ENUM_TYPE.RawValue in item.rawValue }) 
    } 
} 

を最後に、あなたがする必要があるすべては、そのプロトコルにあなたが列挙型を反復処理する必要がある任意の時間に準拠している:

enum TestType: String, EnumIteratable { 
    case unitTest = "Unit Test" 
    case uiTest = "UI Test" 
} 

TestType.getRawValues() 

ここでの利点は、私がintegrationTestの新しいケースを追加できるということです。それを1つの場所に追加するだけです。

+1

これはかなりクールで、元々達成しようとしていたものに近いです。代替ソリューションをありがとう! – JonahGabriel

関連する問題