可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
my object is :
struct Order: Codable {
var item_id:String = ""
var quantity:Int = 0
var image:String = ""
var name:String = ""
var desc:String = ""
}
and the class of function is :
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 []
}
when i try to use this function :
SavedData.saveOrder(value: itemsInCart)
it's not working with me , any help ?!!!
回答1:
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)
}
回答2:
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)
}
回答3:
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")
}
回答4:
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
}
回答5:
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)
}
回答6:
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!
}