web-dev-qa-db-fra.com

Swift NSUserDefaults ne sauvegarde pas le dictionnaire?

J'ai le code de test suivant:

  func testSaveDictionary() {
    let userDefaults = NSUserDefaults.standardUserDefaults()
    var jo = [
      "a" : "1.0",
      "b" : "2.0"
    ]

    let akey = "aKey"
    userDefaults.setObject(jo, forKey: akey)
    var isOk = userDefaults.synchronize()

    var data0 = userDefaults.dictionaryForKey(akey)
    println(data0)

  }

La sortie de println (data0) est nulle.

Quelque chose ne va pas avec mon code? Swift Dictionary est-il considéré comme une liste de propriétés maintenant ou dans la version finale?

22
Sean

Mise à jour pour Swift 2, Xcode 7: Comme @atxe l'a remarqué, les dictionnaires NSUserDefaults sont maintenant mappés comme [String, AnyObject]. Ceci est une conséquence des "génériques légers" d'Objective-C qui permettent de déclarer la méthode Objective-C comme

- (NSDictionary<NSString *,id> *)dictionaryForKey:(NSString *)defaultName

(Les objets par défaut doivent être des listes de propriétés et en particulier les clés de dictionnaire ne peuvent être que des chaînes.)

D'un autre côté, un dictionnaire Swift est ponté automatiquement si possible, donc le code original de la question fonctionne (à nouveau):

let jo = [
    "a" : "1.0",
    "b" : "2.0"
]

let akey = "aKey"
// Swift 2:
userDefaults.setObject(jo, forKey: akey)
// Swift 3:
userDefaults.set(jo, forKey: akey)

Réponse originale pour Swift 1.2: Les valeurs par défaut de l'utilisateur peuvent stocker NSDictionary objets. Ceux-ci sont mappés à Swift as [NSObject : AnyObject]:

var jo : [NSObject : AnyObject] = [
    "a" : "1.0",
    "b" : "2.0"
] 
userDefaults.setObject(jo, forKey: akey)
var isOk = userDefaults.synchronize()

Et notez que dictionaryForKey() renvoie une option, vous devez donc la vérifier par exemple avec une affectation optionnelle:

if let data0 = userDefaults.dictionaryForKey(akey) {
    print(data0)
} else {
    print("not set")
}

// Output: [b: 2.0, a: 1.0]
31
Martin R

Vous devez d'abord le convertir en NSData. Quelque chose comme ça:

var data = NSKeyedArchiver.archivedDataWithRootObject(jo)
var userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(data, forKey:akey) 
12
Anthony Kong

J'ai fait face à ce problème hier et j'ai déposé un radar: Impossible de stocker le dictionnaire dans NSUserDefaults dans iOS8 . Ce problème est uniquement lié à iOS 8. J'ai également décrit une solution de contournement pour ce cas: Solution de contournement pour l'enregistrement du dictionnaire dans NSUserDefaults . Fonctionne comme un charme.

/// Save
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key)

/// Read
var data = NSUserDefaults.standardUserDefaults().objectForKey(key) as NSData
var object = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [String: String]
4
Tomasz Szulc

Suivez ce beau code ci-dessous -> Swift 3

public func setDict(dict: NSDictionary) {
    let data = NSKeyedArchiver.archivedData(withRootObject: dict)
    let userDefaults = UserDefaults.standard
    userDefaults.set(data, forKey:"keyHere")
}


public func getDict() -> NSDictionary {
    let data = UserDefaults.standard.object(forKey: "keyHere") as! NSData
    let object = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as! NSDictionary
    return object;
}
3
Matheus Domingos

// Swift 4.

// pour économiser

    let userDefaults = UserDefaults.standard
    userDefaults.setValue(value, forKey: "Your_Key")
    userDefaults.synchronize()

// pour pour récupérer

        let loadedCart = UserDefaults.standard.dictionary(forKey: "Your_Key")
2
Shashi Verma