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.