web-dev-qa-db-fra.com

Swift - Enregistrer un tableau de dictionnaires dans NSUserDefaults

J'ai un tableau de panier vide -> var cart: [Dictionary<String, Any>] = []

Et j'ai 2 écrans, productsView et resumeView. Dans la vue des produits, j'ai quelques produits. Lorsque l'utilisateur appuie sur un produit, cela va dans le panier:

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

Si l'utilisateur appuie sur plus de produits: 

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

Maintenant, lorsque l’utilisateur a fini d’ajouter des produits au panier, je souhaite afficher la deuxième vue avec la liste des produits. L’utilisateur peut modifier les produits "quantité" ou supprimer des produits. Si l'utilisateur appuie sur le dos et va au premier écran, je veux montrer la liste mise à jour.

Je souhaite utiliser NSUserDefaults pour enregistrer mon tableau et afficher les données mises à jour entre les écrans. Mais j'obtiens l'erreur suivante:

Type '[Dictionary<String, Any>]' does not conform to protocol 'AnyObject'
14
pekpon

edit/update: dans Swift 3, votre type de dictionnaire serait acceptable.

Dictionnaires

Swift établit également des ponts entre le type Dictionary et la classe NSDictionary . Lorsque vous reliez un objet NSDictionary avec des types Paramétrés à un dictionnaire Swift, le dictionnaire obtenu est du type [Key: Valeur]. Si un objet NSDictionary ne spécifie pas paramétré types, il est ponté vers un dictionnaire Swift de type [AnyHashable: Any]

Donc, déclarer votre tableau de dictionnaires comme [[String: Any]] dans Swift 3 serait bien:


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


Vous devez simplement changer la façon dont vous déclarez votre tableau de dictionnaires. Vous devriez utiliser [String: AnyObject] au lieu de [String: Any]. Vous devriez faire comme suit:

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
    }
}
27
Leo Dabus

Vous utilisez tout ce qui n'est pas conforme à AnyObject. Utilisez AnyObject pour déclarer votre dictionnaire,

var cart: [Dictionary<String, AnyObject>] = [["name": "A", "price": "1", "qty": "3"],["name": "B", "price": "2", "qty": "1"]]
0
Sandeep

C'est parce que vous essayez de stocker un tableau en tant que "AnyObject".

Ce que vous devez faire c'est:

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

Vous pouvez ensuite accéder à votre dictionnaire comme ceci:

let yourCartZero = userDefaults.objectForKey("cart0")

Si vous voulez stocker tout le tableau en même temps:

Ensuite, vous pouvez utiliser ceci:

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")
0
Dejan Skledar