类型不符合协议“可编码”

时间:2020-01-11 13:27:11

标签: ios swift codable

我有一个名为Event的类,希望将其设置为可编码:

class Event: Codable {
    let name: String
    let action: String
    let data: [String: Any]?

    enum CodingKeys: String, CodingKey {
        case name
        case action
        case data
    }

    init(name: String, action: String, data: [String: Any]?) {
        self.name = name
        self.action = action
        self.data = data
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try values.decode(String.self, forKey: .name)
        self.action = try values.decode(String.self, forKey: .action)
        let eventDataAsJSONString = try values.decode(String.self, forKey: .data)
        if let eventDataAsData = eventDataAsJSONString.data(using: .utf8) {
            self.data = try? JSONSerialization.jsonObject(with: eventDataAsData, options: []) as? [String: Any]
        } else {
            self.data = nil
        }
    }

    func encode(from encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.name, forKey: .name)
        try container.encode(self.action, forKey: .action)
        if let data = self.data {
            let eventDataAsData = try! JSONSerialization.data(withJSONObject: data, options: [])
            let eventDataAsJSONString = String(data: eventDataAsData, encoding: .utf8)
            try container.encode(eventDataAsJSONString, forKey: .data)
        } else {
            try container.encodeNil(forKey: .data)
        }
    }
}

但我遇到此错误:

Type 'Event' does not conform to protocol 'Encodable'

我同时实现了init(from decoder: Decoder)encode(from encoder: Encoder)。 所以我在这里做错了吗?

我需要使用data类型的[String:Any]属性,因为我的用户需要用它存储一些类似于json的信息。

1 个答案:

答案 0 :(得分:2)

这是在Codable中使用ANY的方式

class Event<T: Codable>: Codable {
    let name: String
    let action: String
    let data: [String: T]?

    enum CodingKeys: String, CodingKey {
        case name
        case action
        case data
    }

    init(name: String, action: String, data: [String: T]?) {
        self.name = name
        self.action = action
        self.data = data
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try values.decode(String.self, forKey: .name)
        self.action = try values.decode(String.self, forKey: .action)
        let eventDataAsJSONString = try values.decode(String.self, forKey: .data)
        if let eventDataAsData = eventDataAsJSONString.data(using: .utf8) {
            self.data = try? JSONSerialization.jsonObject(with: eventDataAsData, options: []) as? [String: T]
        } else {
            self.data = nil
        }
    }

    func encode(from encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(self.name, forKey: .name)
        try container.encode(self.action, forKey: .action)
        if let data = self.data {
            let eventDataAsData = try! JSONSerialization.data(withJSONObject: data, options: [])
            let eventDataAsJSONString = String(data: eventDataAsData, encoding: .utf8)
            try container.encode(eventDataAsJSONString, forKey: .data)
        } else {
            try container.encodeNil(forKey: .data)
        }
    }
}


     let event = Event<String>(name: "name", action: "action", data: ["String" : "String"]) // Replace <String> with the type u want and pass that in data