如何在用户默认中保存对象列表?

How to save list of object in user Default?

我的目标是:

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

函数的class是:

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

    class func getOrder() -> [Order] {
        if let order = UserDefaults.standard.array(forKey: "orderHistoryArray") {
            return order as! [Order]
        }
        return []
    }

当我尝试使用这个功能时:

            SavedData.saveOrder(value: itemsInCart)

它不适合我,有什么帮助吗?!!!

如果您实施 Codable 则使用

do {
     let data = try JSONEncoder().encode(arr)
     // save data here 

     // to load
     let data = //// get it here 
     let arr = try JSONDecoder().decode([Order].self, from: data)
           
   }
   catch {
     print(error)
   }

要使您的 NSKeyedArchiver.archivedData(withRootObject: value) 正常工作,您的 Order 需要符合 Codable 协议。只需将这些添加到您的 Order 结构中,它就可以正常工作。

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")
}

可编码

您可以使用 Codable 保存和加载数组 to/from UserDefaults。

节省

这就是您保存它的方式

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

加载中

这就是您加载它的方式

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
}

您混淆了协议 CodableNSCoding

1) NSCoding

NSKeyed(Un)Archiver 属于 NSCoding。要使用它,您必须将 Order 声明为 class 继承自 NSObject 并采用协议及其所需的方法

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")
    }
}

然后就可以加载和保存数据了

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 你可以保留你的结构。只要采用协议,将编码器创建的Data保存到磁盘

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)
}

您可以只使用 属性 列表编码器和 属性 列表解码器将您的模型保存为用户默认值。很简单:

假设您有一个订单类型的模型,

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
    }
}

一般例子

假设您使用 Json 解码器像这样解码一些数据:

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

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

// 现在您可以轻松地将解码后的模型对象保存到用户默认值

do {
      UserDefaults.standard.set(try PropertyListEncoder().encode(decodedValue), forKey: "Some key")
} catch let err {
      print(err)
}

我用这个 class 来解决这个问题 :

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
}
}

那我就用这个函数来用

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!
}