2015-11-07 47 views
5

我所要做的是創建一個協議擴展到從一個枚舉獲取原始值的數組獲得所有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 
    } 

} 

我怎樣才能實現協議EnumIteratable,這樣我可以調用TestType.getRawValues(),並將它返回所有原始枚舉值的字符串數組?

謝謝!

+0

也許使用MirrorType? –

+0

@MarceloFabri鏡像不能工作的原因有幾個,其中之一就是你實際需要一個枚舉實例,我試圖避免。此外,枚舉不具有屬性:) – 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

斯科特的解決方案可能是你想要的。但是,如果你正在尋找的東西更通用的,可以適用於任意未來的枚舉,並允許更多的情況下,你可以試試這個:

首先,你需要遍歷枚舉情況的方法。我曾經從這裏這個實現: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

這是非常酷,接近我原來試圖完成:)感謝您的替代解決方案! – JonahGabriel