2017-08-04 72 views
0

的多個子類比方說,我有一些JSON,就像這樣:使用可編碼時,JSON輸入表示可編碼類型

{ 
    "some-random-key": { 
         "timestamp": 1234123423 
         "type": "text", 
         "content": "Hello!" 
        }, 

    "some-other-key": { 
         "timestamp": 21341412314 
         "type": "image", 
         "path": "/path/to/image.png" 
        } 
} 

這JSON表示兩個消息的對象。以下是我想代表他們(SWIFT 4):

class Message: Codable { 
    let timestamp: Int 
    // ...codable protocol methods... 
} 

class TextMessage: Message { // first message should map to this class 

    let content: String 

    // ...other methods, including overridden codable protocol methods... 
} 

class ImageMessage: Message { // second message should map to this class 
    let path: String 

    // ...other methods, including overridden codable protocol methods... 
} 

如何使用「類型」屬性在JSON告訴可編碼初始化其子類?我的第一反應是用一個枚舉作爲中介機構,這將允許我去串表示和元類型之間去

enum MessageType: String { 
    case image = "image" 
    case text = "text" 

    func getType() -> Message.Type { 
     switch self { 
     case .text: return TextMessage.self 
     case .image: return ImageMessage.self 
     } 
    } 

    init(type: Message.Type) { 
     switch type { 
     case TextMessage.self: self = .text 
     case ImageMessage.self: self = .image 
     default: break 
     } 
    } 
} 

然而,在init這裏會導致編譯器錯誤 -
Expression pattern of type 'TextMessage.Type' cannot match values of type 'Message.Type'
是否有規範/接受的方式來處理這種情況?爲什麼這裏的init沒有編譯getType函數呢?

回答

0

的「是」關鍵字檢查是否代表元類型元類型的另一個子類。此代碼的工作原理:

init(type: Message.Type) { 
    switch type { 
    case is TextMessage.Type: self = .text 
    case is ImageMessage.Type: self = .text 
    } 
} 
+0

請你能提供一個完整的實例嗎? – Stoff81

+0

@ Stoff81'MessageType(rawValue:value).getType()'會給你這個值的類型,'MessageType(type:TextMessage.self).rawValue'將返回類型的編碼值。 –

+0

嘿,抱歉,但我正在努力看到整個事情作爲一個整體工作。無法讓它編譯。 – Stoff81

0

我會去的這種做法:

static func createMessage(with json: [String: Any]) -> Message? { 
     guard let typeString = json["type"] as? String, 
     let type = MessageType(rawValue: typeString) else { return nil } 
     switch type { 
     case .image: return ImageMessage(....