简体   繁体   中英

No 'decodeIfPresent' candidates produce the expected contextual result type '[ModelMemberSubCategory]!'

I have two custom struct models using Codable . One is ModelMemberCategory & other one is ModelMemberSubCategory which is child of ModelMemberCategory . Here is the code snippet:

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

ModelMemberSubCategory

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

Now the problem is its building in Xcode 9.2 but not in Xcode 9.4.1. While I try to build using 9.4.1 I'm getting error like this:

No 'decodeIfPresent' candidates produce the expected contextual result type '[ModelMemberSubCategory]!'

on

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

I don't know what Apple changed in Xcode 9.4.1 version but can anyone help me to overcome this error?

You need Decodable instead of Encodable . Decodable is needed to represent the external entity to your type

Changing Encodable to Decodable fixes the error.

The code builds in XCode 9.2 because in Swift 4.0(<4.1), the compiler is not checking whether your structs conform to Decodable or not. This got fixed in Swift 4.1(XCode 9.3+), by making use of Conditional conformance.
You can read more about it here.

On a side note, in ModelMemberSubCategory , fieldType is missing. I hope its intentional.
Also, decodeIfPresent returns Optional values but all your instance variables are non-optionals. If you think some variables can be nil, you should make them Optional, so that you can handle nil values in your code in a better way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM