How to save list of object in user Default?

You are mixing up the protocols Codable and NSCoding

1) NSCoding

NSKeyed(Un)Archiver belongs to NSCoding. To use it you have to declare Order as class inheriting from NSObject and to adopt the protocol and its required methods

class Order: NSObject, NSCoding {
    var item_id : String // no need to assign default values
    var quantity : Int
    var image : String
    var name : String
    var desc : String

    required init(coder decoder: NSCoder) 
    {
        item_id = decoder.decodeObject(forKey: "item_id") as! String
        quantity = decoder.decodeInteger(forKey: "quantity")
        image = decoder.decodeObject(forKey: "image") as! String
        name = decoder.decodeObject(forKey: "name") as! String
        desc = decoder.decodeObject(forKey: "desc") as! String
    }

    func encode(with coder: NSCoder) 
    { 
        coder.encode(item_id, forKey: "item_id")
        coder.encode(quantity, forKey: "quantity")
        coder.encode(image, forKey: "image")
        coder.encode(name, forKey: "name")
        coder.encode(desc, forKey: "desc")
    }
}

Then you can load and save the data

class func saveOrder(value: [Order]) {
    print(value)
    let placesData = NSKeyedArchiver.archivedData(withRootObject: value)
    UserDefaults.standard.set(placesData, forKey: "orderHistoryArray")
}

class func getOrder() -> [Order] {
    guard let orderData = UserDefaults.standard.data(forKey: "orderHistoryArray"),
          let order = NSKeyedUnarchiver.unarchiveObject(with: orderData) as? [Order] else { return [] }
    return order
}

2) Codable

With Codable you can keep your struct. Just adopt the protocol and save the Data created by the encoder to disk

struct Order : Codable {
    var item_id : String
    var quantity : Int
    var image : String
    var name : String
    var desc : String
}

// Both methods `throw` to hand over an en-/decoding error to the caller
class func saveOrder(value: [Order]) throws {
    print(value)
    let placesData = try JSONEncoder().encode(value) else { return }
    UserDefaults.standard.set(placesData, forKey: "orderHistoryArray")
}

class func getOrder() throws -> [Order] {
    guard let orderData = UserDefaults.standard.data(forKey: "orderHistoryArray") else { return [] }
    return try JSONDecoder().decode([Order].self, from: orderData)
}

Leave a Comment