Swift扩展-约束扩展必须在非专用泛型'Array'上声明

时间:2018-12-18 02:08:49

标签: ios swift collections swift-extensions type-alias

我有一个API,该API返回对象的JSON数组。我将结构设置如下:

typealias MyModels = [MyModel]

struct MyModel: Codable {
    let field1: String
    let field2: String
    let mySubModel: SubModel?

    enum CodingKeys: String, CodingKey {
        case field1 = "Field1"
        case field2 = "Field2"
        case mySubModel = "MySubModel"
    }
}

struct SubModel: Codable {
    let subModelField1: String
    let subModelField2: String

    enum CodingKeys: String, CodingKey {
        case subModelField1 = "SubModelField1"
        case subModelField2 = "SubModelField2"
    }
}

我要做的是添加此扩展,提供路径var(NetworkModel协议为API操作提供了一些基本功能):

extension MyModels: NetworkModel {
    static var path = "the/endpoint/path"
}

当基是对象或json键时,以这种方式设置的其他模型/结构类中没有任何问题。但是,由于这是一个不同的对象,并且仅仅是一个数组,所以当我将该扩展放入类时会遇到此错误:

Constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause

我做了一些挖掘工作,并在扩展名的where子句中做了一些尝试,但是我对它想要的东西有些困惑。我敢肯定这很简单,但是对此有何想法?如果我需要使用上面的typealias进行其他处理,那很好。预先感谢!

2 个答案:

答案 0 :(得分:6)

我想你是说

extension MyModels: NetworkModel {

有错误吗?您似乎错过了一个s

该错误基本上是告诉您执行此操作:

extension Array : NetworkModel where Element == MyModel {
    static var path = "the/endpoint/path"
}

您不能简单地扩展[MyModel]

答案 1 :(得分:0)

尽管Sweeper会根据最初的问题适当地回答了这个问题,但我想提供一种替代方法,即使可能稍微复杂一些。这可以通过覆盖事物的“可分解性”一面并手动将模型放入列表中来实现:

struct MyModels: Codable {
    var modelList: [MyModel] = []

    public init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        let metaType = (Account.self as Decodable.Type)

        while !container.isAtEnd {
            let subdecoder = try container.superDecoder()
            if let model = try metaType.init(from: subdecoder) as? MyModel {
                modelList.append(model)
            }
        }
    }
}

struct MyModel: Codable {
    let subModelField1: String
    let subModelField2: String

    enum CodingKeys: String, CodingKey {
        case subModelField1 = "SubModelField1"
        case subModelField2 = "SubModelField2"
    }
}

extension MyModels: NetworkModel {
    static var path = "the/endpoint/path"
}