【问题标题】:Swift extension - Constrained extension must be declared on the unspecialized generic type 'Array'Swift 扩展 - 必须在非专用泛型类型“数组”上声明约束扩展
【发布时间】:2019-05-18 10:11:14
【问题描述】:

我有一个返回 JSON 对象数组的 API。我已将结构设置为如下所示:

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

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

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

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

约束扩展必须在非特化泛型类型“数组”上声明,约束由“where”子句指定

我已经进行了一些挖掘并尝试了一些关于扩展的 where 子句的事情,但我对它想要什么感到有点困惑。我敢肯定这很简单,但是对此有什么想法吗?如果我需要使用上面的 typealias 以不同的方式处理它,我可以接受。提前致谢!

【问题讨论】:

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


    【解决方案1】:

    我猜你的意思是

    extension MyModels: NetworkModel {
    

    有错误吗?你好像错过了s

    错误基本上是告诉你这样做:

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

    你不能简单地扩展[MyModel]

    【讨论】:

    • 感谢您的回复。是的,你是对的,我的意思是在那里有“s”(现在在我的原始帖子中更正)。当我将其更改为您在此处放置的内容时,出现 2 个错误:“未使用闭包表达式”,然后我的静态 var 上出现错误:“静态属性只能在类型上声明”。想法?
    • 抱歉,我很困惑。 static 是我们提供 API 路径所需的字符串 var。上面的代码没有按原样编译,我还不知道为什么。格式不正确吗?似乎认为这条线上有一个封闭。对不起,我的困惑。
    • @svguerin3 我意识到我最后的评论是一个错误。继续使用static。我已经编辑了答案以包含您需要的确切代码。你能展示你写的东西吗?
    【解决方案2】:

    尽管 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"
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      相关资源
      最近更新 更多