首页 > 解决方案 > 没有“decodeIfPresent”候选产生预期的上下文结果类型“[ModelMemberSubCategory]!”

问题描述

我有两个使用Codable. 一个是ModelMemberCategory& 另一个ModelMemberSubCategory是 的子级ModelMemberCategory。这是代码片段:

模型成员类别

struct ModelMemberCategory: Encodable {

    var catId : Int!
    var catName : String!
    var fields : [ModelMemberSubCategory]!

    //For Codable

    enum CodingKeys: String, CodingKey {
        case catId = "cat_id"
        case catName = "cat_name"
        case fields = "fields"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        catId = try values.decodeIfPresent(Int.self, forKey: .catId)
        catName = try values.decodeIfPresent(String.self, forKey: .catName)
        fields = try values.decodeIfPresent([ModelMemberSubCategory].self, forKey: .fields) // This line throws error on Xcode 9.4.1 but not on Xcode 9.2
    } 
}

模型成员子类别

struct ModelMemberSubCategory: Encodable{

    var fieldCategory : String!
    var fieldCode : String!
    var fieldDatatype : String!
    var fieldId : Int!
    var fieldName : String!
    var fieldType : String!
    var fieldValue : String!
    var fieldValuetype : String!
    var fieldVisible : String!


    //Codable
    enum CodingKeys: String, CodingKey {
        case fieldCategory = "field_category"
        case fieldCode = "field_code"
        case fieldDatatype = "field_datatype"
        case fieldId = "field_id"
        case fieldName = "field_name"
        case fieldValue = "field_value"
        case fieldValuetype = "field_valuetype"
        case fieldVisible = "field_visible"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        fieldCategory = try values.decodeIfPresent(String.self, forKey: .fieldCategory)
        fieldCode = try values.decodeIfPresent(String.self, forKey: .fieldCode)
        fieldDatatype = try values.decodeIfPresent(String.self, forKey: .fieldDatatype)
        fieldId = try values.decodeIfPresent(Int.self, forKey: .fieldId)
        fieldName = try values.decodeIfPresent(String.self, forKey: .fieldName)
        fieldValue = try values.decodeIfPresent(String.self, forKey: .fieldValue)
        fieldValuetype = try values.decodeIfPresent(String.self, forKey: .fieldValuetype)
        fieldVisible = try values.decodeIfPresent(String.self, forKey: .fieldVisible)
    }
}

现在的问题是它在 Xcode 9.2 中的构建,而不是在 Xcode 9.4.1 中。当我尝试使用 9.4.1 构建时,我收到如下错误:

没有“decodeIfPresent”候选产生预期的上下文结果类型“[ModelMemberSubCategory]!”

fields = try values.decodeIfPresent([ModelMemberSubCategory].self, forKey: .fields)ModelMemberCategory

我不知道 Apple 在 Xcode 9.4.1 版本中发生了什么变化,但谁能帮我克服这个错误?

标签: iosswiftmodelcodable

解决方案


你需要Decodable而不是Encodable. Decodable需要将外部实体表示为您的类型

更改EncodableDecodable修复错误。

代码在 XCode 9.2 中构建,因为在 Swift 4.0(<4.1) 中,编译器不会检查您的结构是否符合 Decodable。通过使用条件一致性,这在 Swift 4.1(XCode 9.3+)中得到了修复。
你可以在这里阅读更多关于它的信息。

在旁注中, in ModelMemberSubCategoryfieldType是缺失的。我希望它是故意的。
此外,decodeIfPresent返回Optional值,但您的所有实例变量都是非可选的。如果您认为某些变量可以为 nil,则应将它们设为 Optional,以便您可以更好地处理代码中的 nil 值。


推荐阅读