为什么我的特殊Codable协议与Swift的带有数组的Codable协议工作原理不同?

时间:2019-02-25 21:10:31

标签: swift protocols codable swift4.2

使用Codable,我可以创建以下扩展名

extension Decodable {
    public static func decode(data: Data, decoder: JSONDecoder = .default) -> Self? {
        do {
            return try decoder.decode(self, from: data)
        } catch let error as NSError {
            CodableKit.log(message: "\(error.userInfo)")
            return nil
        }
    }
}

并将其用于单个对象和数组类型,例如

let person = Person.decode(data: personData)   // single
let people = [Person].decode(data: peopleData) // array 

上面的两行编译没有问题。

现在,我想创建一个类似于Codable

的新协议
public typealias JsonCodable = JsonDecodable & JsonEncodable

public protocol JsonDecodable: Decodable {
    static func decode(data: Data?, decoder: JSONDecoder) -> Self?
}

extension JsonDecodable {
    static func decode(data: Data?, decoder: JSONDecoder) -> Self? {
        ....
    }
}

当我尝试像使用JsonDecodable一样使用Codable时,出现以下编译器错误

  

类型“ [人]”没有成员“解码”;

let person = Person.decode(data: personData)   // this works
let people = [Person].decode(data: peopleData) // this does not

我如何获得JsonDecodable来解码模型数组,就像扩展Codable一样?

1 个答案:

答案 0 :(得分:3)

如果使用错误的类型名称,该错误消息可能更有用:

  

类型'Array '没有成员'decode';

Person可能符合您的协议,但Array不符合您的协议。 Swift明确声明ArrayDecodable(如果它们的元素是)。您只需要这样做:

extension Array : JsonDecodable where Element : JsonDecodable {
    static func decode(data: Data?, decoder: JSONDecoder) -> Self? {
        // Decode each element and return an array
    }
}

这使用了称为"Conditional Conformance"的功能,该功能通常允许容器在符合容器类型的前提下也遵循协议。