2014-12-07 17 views
8

Có cách nào để ánh xạ giá trị không theo nghĩa đen như tuple của từ điển vào enums không? Mã sau sẽ ném Raw value for enum must be literal.enum các giá trị không theo nghĩa đen trong Swift

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": ""] 
} 

Đó là cùng khi tôi sử dụng các bộ:

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

Giá trị thô cho enums phải hoặc có thể chuyển đổi thành số nguyên, số dấu phẩy động, chuỗi hoặc ký tự đơn. – i40west

Trả lời

4

Tham chiếu ngôn ngữ, khi nói về Enumeration Declaration, nêu rõ rằng:

loại liệu có giá trị phải phù hợp với Giao thức tương đương và một trong các giao thức chuyển đổi theo nghĩa đen: IntegerLiteralConvertible cho các chữ số nguyên, FloatingPointLiteralConvertible cho các ký tự dấu phẩy động, StringLiteralConvertible cho các chuỗi ký tự t hat chứa bất kỳ số ký tự nào và ExtendedGraphemeClusterLiteralConvertible cho chuỗi ký tự chuỗi chỉ chứa một ký tự đơn.

Vì vậy, không có gì khác ngoài các giá trị có thể được sử dụng làm giá trị thô.

Sự chỉnh sửa có là đại diện cho từ điển như là một chuỗi - ví dụ, bạn có thể tách các yếu tố bằng dấu phẩy, và chính từ giá trị với ruột:

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

Sau đó, sử dụng một tài sản tính (hoặc một phương pháp nếu bạn thích), hãy tạo lại từ điển:

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 cung cấp giải pháp thay thế nhưng không trả lời câu hỏi thực tế.

Xác định enum của bạn.

enum FileType { 

    case Image, Video 
} 

Cho trường hợp các giá trị không phải chữ, bất kỳ loại nào bạn muốn phù hợp với giao thức RawRepresentable. Làm điều đó bằng cách mở rộng enum để có mã sạch hơn.

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/") 
     } 
    } 
} 

Để có thể khớp Tuple khi chuyển đổi, hãy triển khai toán tử đối sánh mẫu.

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

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

Và thats nó ...

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

Hãy nói rằng tôi đã trả lời câu hỏi mà không chất vấn. Bây giờ ... Enums (trong Swift ít nhất) được thiết kế để có trường hợp duy nhất. Hãy thận trọng với cách giải quyết này là bạn có thể (tôi hy vọng tình cờ) giữ cùng một số rawValue cho nhiều trường hợp hơn. Nói chung mã ví dụ của bạn có mùi với tôi. Trừ khi bạn (vì lý do rất hợp lý) cần phải tạo ra giá trị enum mới từ tuple, hãy xem xét thiết kế lại. Nếu bạn muốn đi với workaround này, tôi đề nghị (phụ thuộc vào dự án) để thực hiện một số kiểm tra nếu tất cả các trường hợp nguyên giá trị là duy nhất. Nếu không, hãy xem xét điều này:

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/" 
    } 
} 
Các vấn đề liên quan