How to save list of object in user Default?

后端 未结 6 1277
故里飘歌
故里飘歌 2020-12-01 23:07

my object is :

 struct Order: Codable {
        var item_id:String = \"\"
        var quantity:Int = 0
        var image:String = \"\"
        var name:Strin         


        
相关标签:
6条回答
  • 2020-12-01 23:34

    I use this class to solve that :

    class Order: NSObject, NSCoding {
    
    
    var item_id:String = ""
    var quantity:String = ""
    var image:String = ""
    var name:String = ""
    var desc:String = ""
    
    init(item_id: String ,quantity : String , image : String , name: String, desc: String){
        self.item_id = item_id
        self.quantity = quantity
        self.image = image
        self.name = name
        self.desc = desc
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(item_id, forKey: "item_id")
        aCoder.encode(quantity, forKey: "quantity")
        aCoder.encode(image, forKey: "image")
        aCoder.encode(name, forKey: "name")
        aCoder.encode(desc, forKey: "desc")
    }
    
    required init?(coder aDecoder: NSCoder) {
        self.item_id = aDecoder.decodeObject(forKey: "item_id") as! String
        self.quantity = aDecoder.decodeObject(forKey: "quantity") as! String
        self.image = aDecoder.decodeObject(forKey: "image") as! String
        self.name = aDecoder.decodeObject(forKey: "name") as! String
        self.desc = aDecoder.decodeObject(forKey: "desc") as! String
    }
    }
    

    then i use this functions to use it

    class func save(value : Order){
        var orderArray:[Order] = retrive()
        orderArray.append(value)
        let orderArrayAchived = NSKeyedArchiver.archivedData(withRootObject: orderArray)
        UserDefaults.standard.set(orderArrayAchived, forKey: "orderArray")
    }
    
    class func saveListOfOrder(value: [Order]) {
        print(value)
        let cartArrayAchived = NSKeyedArchiver.archivedData(withRootObject: value)
        UserDefaults.standard.set(cartArrayAchived, forKey: "orderArray")
    }
    
    class func retrive()-> [Order]{
        let orderData = UserDefaults.standard.object(forKey: "orderArray") as? NSData
        if orderData == nil
        {
            return [Order]()
        }
        let orderArray = NSKeyedUnarchiver.unarchiveObject(with: orderData! as Data) as? [Order]
        return orderArray!
    }
    
    0 讨论(0)
  • 2020-12-01 23:40

    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)
    }
    
    0 讨论(0)
  • 2020-12-01 23:44

    For your NSKeyedArchiver.archivedData(withRootObject: value) to work, your Order needs to conform to the Codable protocol. Just add these in your Order struct to this and it should work just fine.

    required public init(coder decoder: NSCoder) {
    
        item_id = decoder.decodeObject(forKey: "item_id") as? String ?? ""
        quantity = decoder.decodeObject(forKey: "quantity") as? Int ?? 0
        image = decoder.decodeObject(forKey: "image") as? String ?? ""
        name = decoder.decodeObject(forKey: "name") as? String ?? ""
        desc = decoder.decodeObject(forKey: "desc") as? String ?? ""
    
    }
    
    public 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")
    }
    
    0 讨论(0)
  • 2020-12-01 23:52

    If you implement Codable then use

    do {
         let data = try JSONEncoder().encode(arr)
         // save data here 
    
         // to load
         let data = //// get it here 
         let arr = try JSONDecoder().decode([Order].self,data)
    
       }
       catch {
         print(error)
       }
    
    0 讨论(0)
  • 2020-12-01 23:53

    Codable

    You can save and load your array to/from UserDefaults using Codable.

    Saving

    This is how you save it

    class func saveOrders(_ orders: [Order]) {
        guard let data = try? JSONEncoder().encode(orders) else { return }
        UserDefaults.standard.set(data, forKey: "orders")
    }
    

    Loading

    And this is how you load it

    class func loadOrders() -> [Order] {
        guard
            let data = UserDefaults.standard.data(forKey: "orders"),
            let orders = try? JSONDecoder().decode([Order].self, from: data)
        else { return [] }
        return orders
    }
    
    0 讨论(0)
  • 2020-12-01 23:55

    You can just use Property list encoder and Property list decoder to save your model to User Defaults. Its easy:

    Suppose you have a model of type Order,

    class func saveOrder(value: [Order]) {
        PropertyListEncoder().encode(value), forKey: "Somekey")
    }
    
    class func getOrder() -> [Order]? {
        if let data = UserDefaults.standard.value(forKey: "Somekey") as? Data {
            let orderDetail = try? PropertyListDecoder().decode([Order].self, from: data)
            return orderDetail!
        } else {
            return nil
        }
    }
    

    general example

    Suppose you use Json Decoder to decode some data like so:

    let decodedValue = try JSONDecoder().decode(Order.self, from: data)
    

    OR

    let decodedValue : Order = Order(a: 1, b: 0) // your order model value type,
    

    // Now you can save the decoded model object to User defaults easily

    do {
          UserDefaults.standard.set(try PropertyListEncoder().encode(decodedValue), forKey: "Some key")
    } catch let err {
          print(err)
    }
    
    0 讨论(0)
提交回复
热议问题