Ios 如何以用户默认值保存对象列表?

Ios 如何以用户默认值保存对象列表?,ios,arrays,swift,list,nsuserdefaults,Ios,Arrays,Swift,List,Nsuserdefaults,我的目标是: struct Order: Codable { var item_id:String = "" var quantity:Int = 0 var image:String = "" var name:String = "" var desc:String = "" } 函数的类别是: class func saveOrder(value: [Order]) { pri

我的目标是:

 struct Order: Codable {
        var item_id:String = ""
        var quantity:Int = 0
        var image:String = ""
        var name:String = ""
        var desc:String = ""
    }
函数的类别是:

    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,data)

   }
   catch {
     print(error)
   }

要使您的
NSKeyedArchiver.archivedData(withRootObject:value)
正常工作,您的
订单
需要符合
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将数组保存到UserDefaults或从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
}

您混淆了协议
Codable
NSCoding

1)编码

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
可以保留结构。只需采用协议并将编码器创建的
数据
保存到磁盘

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

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

假设您有一个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
    }
}
一般示例

假设您使用Json解码器解码某些数据,如下所示:

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

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

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

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

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

我添加了一个使用属性列表编码器的答案,这是在将数据放入用户默认值之前对其进行编码的正确方法。如果您需要帮助了解,请告诉我,因为Swift 4不是正确的解决方案。您应该使用其他人评论的可编码协议。
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!
}