2014-12-07 122 views
8

有沒有任何方法將像字典元組這樣的非文字值映射爲枚舉?以下代碼將拋出Raw value for enum must be literalSwift中的非文字值的枚舉

enum FileType { 
    case VIDEO = ["name": "Video", "contentTypeMatcher": "video/"] 
    case IMAGE = ["name": "Image", "contentTypeMatcher": "image/"] 
    case AUDIO = ["name": "Audio", "contentTypeMatcher": "aduio/"] 
    case PDF = ["name": "PDF", "contentTypeMatcher":"application/pdf"] 
    case TEXT = ["name": "Text", "contentTypeMatcher": "text/"] 
    case FOLDER= ["name": "Folder", "contentTypeMatcher" :"application/x-directory"] 
    case PLAIN = ["name": "Plain", "contentTypeMatcher": ""] 
} 

這是一樣的,當我使用的元組:

enum FileType { 
    case VIDEO = (name: "Video", contentTypeMatcher: "video/") 
    case IMAGE = (name: "Image", contentTypeMatcher: "image/") 
    case AUDIO = (name: "Audio", contentTypeMatcher: "aduio/") 
    case PDF = (name: "PDF", contentTypeMatcher:"application/pdf") 
    case TEXT = (name: "Text", contentTypeMatcher: "text/") 
    case FOLDER = (name: "Folder", contentTypeMatcher :"application/x-directory") 
    case PLAIN = (name: "Plain", contentTypeMatcher: "") 
} 
+0

枚舉的原始值必須是或可轉換爲整數,浮點數,字符串或單個字符。 – i40west 2014-12-07 20:41:04

回答

4

語言參考,談論Enumeration Declaration時,明確指出:

的原始值類型必須符合Equatable協議和以下文字轉換協議之一:IntegerLiteralConvertible用於整數文字,FloatingPointLiteralConvertible用於浮點文字,StringLiteralConvertible用於字符串文字t hat包含任意數量的字符,而ExtendedGraphemeClusterLiteralConvertible僅包含單個字符的字符串文字。

所以沒有其他文字可以用作原始值。

一種可能的解決方法是將表示字典作爲一個字符串 - 例如,可以用冒號分開值用逗號的元件,並且鍵:使用計算屬性

enum FileType : String { 
    case VIDEO = "name:Video,contentTypeMatcher:video/" 
    case IMAGE = "name:Image,contentTypeMatcher:image/" 
    ... 
} 

然後,(或方法如果你喜歡),重建字典:

var dictValue: [String : String] { 
    var dict = [String : String]() 

    var elements = self.rawValue.componentsSeparatedByString(",") 
    for element in elements { 
     var parts = element.componentsSeparatedByString(":") 
     if parts.count == 2 { 
      dict[parts[0]] = parts[1] 
     } 
    } 

    return dict 
} 
4

@Antonio給出瞭解決方法,但沒有回答實際問題。

定義您的枚舉。

enum FileType { 

    case Image, Video 
} 

給例非文字值,無論何種類型要與符合RawRepresentable協議。通過枚舉擴展實現更清晰的代碼。

extension FileType: RawRepresentable { 

    typealias Tuple = (name: String, contentTypeMatcher: String) 

    private static let allCases = [FileType.Image, .Video] 

    // MARK: RawRepresentable 

    typealias RawValue = Tuple 

    init?(rawValue: Tuple) { 

     guard let c = {() -> FileType? in 

      for iCase in FileType.allCases { 
       if rawValue == iCase.rawValue { 
        return iCase 
       } 
      } 
      return nil 

     }() else { return nil } 
     self = c 
    } 

    var rawValue: Tuple { 

     switch self { 
     case .Image: return Tuple("Image", "image/") 
     case .Video: return Tuple("Video", "video/") 
     } 
    } 
} 

爲了能夠在交換機中匹配Tuple,實現模式匹配運算符。

private func ~= (lhs: FileType.Tuple, rhs: FileType.Tuple) -> Bool { 

    return lhs.contentTypeMatcher == rhs.contentTypeMatcher && lhs.name == rhs.name 
} 

並且那它...

let a = FileType.Image 
print(a.rawValue.name) // "Image" 
let b = FileType(rawValue: a.rawValue)! 
print(a == b) // "true" 
print(b.rawValue.contentTypeMatcher) // "image/" 

比方說,我回答了這個問題沒有質疑。現在...枚舉(至少在Swift中)被設計爲具有獨特的情況。注意這個解決方法是,你可以(我希望不小心)爲更多的情況持有相同的rawValue。通常您的示例代碼會讓我聞到氣味。除非你(出於非常合理的原因)需要從元組中創建新的枚舉值,否則考慮重新設計。如果你想用這個解決方法,我建議(取決於項目)實施一些檢查,如果所有案例原始值是唯一的。如果沒有,請考慮以下內容:

enum FileType { 

    case Video, Image 

    var name: String { 
     switch self { 
     case .Image: return "Image" 
     case .Video: return "Video" 
    } 

    var contentTypeMatcher: String { 
     switch self { 
     case .Image: return "image/" 
     case .Video: return "video/" 
    } 
}