1

I have a Decodable struct like so...

struct BestWishes: Decodable {

    private enum CodingKeys : String, CodingKey {
        case customerID = "customer_id"
        case birthDate = "birth_date"
         case type = "type"
        case customerName = "customer_name"
        case mobileNo = "mobile_number"
    }
    let customerID: Int
    let date: String
    let type: String
    let customerName : String
    let mobileNumber: Int

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        customerID = try container.decode(Int.self, forKey: .customerID)
        type = try container.decode(String.self, forKey: .type)
        if type == "anniversary_date" {
            date = try container.decode(String.self, forKey: .anniversaryDate)
        } else {
            date = try container.decode(String.self, forKey: .birthDate)
        }
        customerName = try container.decode(String.self, forKey: .customerName)
        mobileNumber = try container.decode(Int.self, forKey: .mobileNo)
    }
}

And all the data within this is stored in an array like so..

var bestWishesArr = [BestWishes]()
self.bestWishesArr.append(contentsOf: result.bestWishes) 

Now I would like to store bestWishesArr to Userdefaults. Not sure how to achieve that...

  • Use keyarchiver. Please refer the below https://stackoverflow.com/a/37983027/1142743 – Vinodh Jan 11 '18 at 13:21
  • No @Vinodh it doesn't seem to work. My struct is of type Decodable –  Jan 11 '18 at 13:35
  • its possible then y accepted the answer. without knowing/trying anything just don't tell that its not possible – Vinodh Jan 12 '18 at 06:33

1 Answers1

2

Add the second half of the Codable protocol. To be compatible with the init method the date property is saved differently depending on type

struct BestWish: Codable {

    private enum CodingKeys : String, CodingKey {
        case customerID = "customer_id"
        case birthDate = "birth_date"
        case anniversaryDate = "anniversary_date"
        case type
        case customerName = "customer_name"
        case mobileNumber = "mobile_number"
    }
    let customerID: Int
    let date: String
    let type: String
    let customerName : String
    let mobileNumber: Int

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        customerID = try container.decode(Int.self, forKey: .customerID)
        type = try container.decode(String.self, forKey: .type)
        if type == "anniversary_date" {
            date = try container.decode(String.self, forKey: .anniversaryDate)
        } else {
            date = try container.decode(String.self, forKey: .birthDate)
        }
        customerName = try container.decode(String.self, forKey: .customerName)
        mobileNumber = try container.decode(Int.self, forKey: .mobileNumber)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(customerID, forKey: .customerID)
        try container.encode(type, forKey: .type)
        if type == "anniversary_date" {
            try container.encode(date, forKey: .anniversaryDate)
        } else {
            try container.encode(date, forKey: .birthDate)
        }
        try container.encode(customerName, forKey: .customerName)
        try container.encode(mobileNumber, forKey: .mobileNumber)
    }
}

Then encode the array and write the Data object to UserDefaults

do {
    let jsonData = try JSONEncoder().encode(bestWishesArr)
    UserDefaults.standard.set(jsonData, forKey:"bestWishes")
} catch { print(error) }
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Once again, Thanks @vadian. The answer really helped! Have given . an upvote too...:) –  Jan 11 '18 at 14:05
  • and just a doubt..is there any `isExist` kind of method in json..to check if a certain key exists or not...? –  Jan 11 '18 at 14:06
  • Either make the property optional, or `decodeIfPresent`. **Please** read the documentation about JSON en-/decoding. It's worth it. – vadian Jan 11 '18 at 14:07
  • @v.bw don't use UserDefaults to store your app data. UserDefaults it is meant to store your app settings (i.e. UISwitch states). Just write the resulting JSON data into a json file inside your App support directory – Leo Dabus Jan 11 '18 at 16:49
  • Btw you should also store your dates as Date using the proper dateStrategyDecoding option and store mobile numbers as strings. – Leo Dabus Jan 11 '18 at 16:52