Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Save Array of dictionaries into NSUserDefaults

I have an empty cart array -> var cart: [Dictionary<String, Any>] = []

And I have 2 screens, productsView and resumeView. Into the products view I have some products. When the user taps on a product, this goes to the the cart:

cart = [[name: "A", price: "1", qty: "1"]]

If the user taps on more products:

cart = [[name: "A", price: "1", qty: "3"],[name: "B", price: "2", qty: "1"]]

Now, when the user has finished adding products to the cart, I want to show the second view with the products list, and the user can make changes to the products "qty" or delete products. If the user taps on back and goes to the first screen, I want to show the updated list.

I want to use NSUserDefaults to save my array and show the updated data between screens. But I'm getting the next error:

Type '[Dictionary<String, Any>]' does not conform to protocol 'AnyObject'
like image 238
pekpon Avatar asked Apr 10 '15 07:04

pekpon


2 Answers

edit/update: in Swift 3 your dictionary type would be ok.

Dictionaries

Swift also bridges between the Dictionary type and the NSDictionary class. When you bridge from an NSDictionary object with parameterized types to a Swift dictionary, the resulting dictionary is of type [Key: Value]. If an NSDictionary object does not specify parameterized types, it is bridged to a Swift dictionary of type [AnyHashable: Any]

So declaring your array of dictionaries as [[String: Any]] in Swift 3 would be fine:


Xcode 8 • Swift 3

var cart: [[String: Any]] = []
cart.append(["name": "A", "price": 19.99, "qty": 1])
cart.append(["name": "B", "price": 4.99, "qty": 2])

UserDefaults.standard.set(cart, forKey: "myCart")

if let loadedCart = UserDefaults.standard.array(forKey: "myCart") as? [[String: Any]] {
    print(loadedCart)  // [[price: 19.99, qty: 1, name: A], [price: 4.99, qty: 2, name: B]]"
    for item in loadedCart {
        print(item["name"]  as! String)    // A, B
        print(item["price"] as! Double)    // 19.99, 4.99
        print(item["qty"]   as! Int)       // 1, 2
    }
}


You just need to change the way you are declaring your array of dictionaries. You should use [String: AnyObject] instead of [String: Any]. You should do as follow:

Swift 2.3

var cart: [[String: AnyObject]] = []
cart.append(["name": "A", "price": 19.99, "qty": 1])
cart.append(["name": "B", "price": 4.99, "qty": 2])

NSUserDefaults().setObject(cart, forKey: "myCart")

if let loadedCart = NSUserDefaults().arrayForKey("myCart") as? [[String: AnyObject]] {
    print(loadedCart)  // [[price: 19.99, qty: 1, name: A], [price: 4.99, qty: 2, name: B]]"

    for item in loadedCart {
        print(item["name"] as! String)  // A, B
        print(item["price"] as! Double) // 19.99, 4.99
        print(item["qty"] as! Int)      // 1, 2
    }
}
like image 99
Leo Dabus Avatar answered Nov 14 '22 19:11

Leo Dabus


This is beacause you are trying to store an array as "AnyObject".

What you need to do is:

var counter = 0
for c in cart
{
      userDefaults.setObject(c, forKey: "cart\(counter)")
      counter++
}

You can then access your dictionary like this:

let yourCartZero = userDefaults.objectForKey("cart0")

If you want to store the whole array at the same time:

Then you can use this:

var saving: Dictionary<String, [Dictionary<String, Any>]>

var cart: [Dictionary<String, Any>] = []

var savingCart: Dictionary<String, [Dictionary<String, Any>]> = ["savedCard" : cart]

userDefaults.setObject(savingCart, forKey: "Carts")
like image 1
Dejan Skledar Avatar answered Nov 14 '22 19:11

Dejan Skledar