There is a way to make my on code function for my codable struct, the problem I'm facing is that I can encode it from network but not decode from userdefaults. Here is the implementation of the struct.
struct profile: Codable{
var id: Int?
var firstName: String?
var lastName: String?
var description: String?
var gender: String?
var birthDate: Date?
var smoke: Bool?
var findHouse: Bool?
var hasRoom: Bool?
var sociable: Int?
var ordered: Int?
var athlete: Int?
var party: Int?
var domestic:Int?
var gamer: Int?
var usersId: Int?
var imageId: Int?
var createdAt: Date?
var updatedAt: Date?
var image: imageModel?
var tags: [String]?
enum CodingKeys: String, CodingKey {
case id
case firstName = "first_name"
case lastName = "last_name"
case description
case gender
case birthDate = "birth_date"
case smoke
case findHouse = "find_house"
case hasRoom = "has_room"
case sociable
case ordered
case athlete
case party
case domestic
case gamer
case usersId = "users_id"
case imageId = "image_id"
case createdAt = "created_at"
case updatedAt = "updated_at"
case image
case tags
}
init(){
}
init(from decoder: Decoder) throws {
print("going to decode from decoder showing results")
let values = try decoder.container(keyedBy: CodingKeys.self)
self.id = (try values.decodeIfPresent(Int.self, forKey: .id))
print("id value \(self.id)")
self.firstName = (try values.decodeIfPresent(String.self, forKey: .firstName))
print("name value \(self.firstName)")
self.lastName = (try values.decodeIfPresent(String.self, forKey: .lastName))
print("lastname value \(lastName)")
self.description = (try values.decodeIfPresent(String.self, forKey: .description))
print("description value \(description)")
self.gender = (try values.decodeIfPresent(String.self, forKey: .gender))
print("gender value \(gender)")
if let date = try values.decodeIfPresent(String.self, forKey: .birthDate){
print("date value \(date)")
self.birthDate = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
print("after conversion \(self.birthDate)")
}else{
self.birthDate = nil
}
self.smoke = (try values.decodeIfPresent(Int.self, forKey: .smoke)) == 0 ? false : true
print("smoke value \(smoke)")
self.findHouse = (try values.decodeIfPresent(Int.self, forKey: .findHouse)) == 0 ? false : true
print("findhouse value \(findHouse)")
self.hasRoom = (try values.decodeIfPresent(Int.self, forKey: .hasRoom)) == 0 ? false : true
print("has romm value \(hasRoom)")
self.sociable = (try values.decodeIfPresent(Int.self, forKey: .sociable))
print("sociable value\(sociable)")
self.ordered = (try values.decodeIfPresent(Int.self, forKey: .ordered))
print("orderder value \(ordered)")
self.athlete = (try values.decodeIfPresent(Int.self, forKey: .athlete))
print("athlete value \(athlete)")
self.party = (try values.decodeIfPresent(Int.self, forKey: .party))
self.domestic = (try values.decodeIfPresent(Int.self, forKey: .domestic))
self.gamer = (try values.decodeIfPresent(Int.self, forKey: .gamer))
self.usersId = (try values.decodeIfPresent(Int.self, forKey: .usersId))
self.imageId = (try values.decodeIfPresent(Int.self, forKey: .imageId))
if let date = try values.decodeIfPresent(String.self, forKey: .createdAt){
self.createdAt = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
}else {
self.createdAt = nil
}
if let date = try values.decodeIfPresent(String.self, forKey: .updatedAt){
self.updatedAt = Date(fromString: String(date.dropLast(10)), format: .custom("yyyy-MM-dd"))
}else{
self.updatedAt = nil
}
self.image = (try values.decodeIfPresent(imageModel.self, forKey: .image))
self.tags = (try values.decodeIfPresent([String].self, forKey: .tags))
}
}
This is the code to save to userdefaults.standard:
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(requestManager.instance.user) {
UserDefaults.standard.set(encoded, forKey: "user")
if let json = String(data: encoded, encoding: .utf8) {
print("reading value in userDefault \(json)")
}
}
so when I try to decode from userDefaults with this code:
let decoder = JSONDecoder()
if let user = UserDefaults.standard.data(forKey: "user"){
print("data for user \(user)")
do{
let question = try decoder.decode(profile.self, from: user)
print("birthDate from decoder \(question.birthDate)")
print("id from decoder \(question.id)")
print("name from decoder \(question.firstName)")
if question.id != nil {
print("the id is not Nil \(question)")
requestManager.instance.user = question
}
}catch{
print(error.localizedDescription)
print("el valor de birthDate in \(requestManager.instance.user.birthDate)")
}
}
After this I got those messages in console
going to decode from decoder. id value Optional(3). name value Optional("Yoel "). Data cannot be read because does not have the right format.
What I guess is date type in fields birthDate, createdAt and updatedAt.
So what I want to try is to create a custom encoder because in decoder is expecting a String and should be returning a Date value.
init(fromyou have to do the opposite inencode(- vadianhasRoomasBool(with the synthesized encoder) but you decode it asIntwhich causes a type mismatch. With respect and no offense but your entire struct is a mess. 😉 - vadianCodableprotocol all encoded and decoded types must match. - vadian