pekpon pekpon - 1 month ago 25
Swift Question

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'

Answer

edit/update: in Swift 3 You 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
    }
}