web-dev-qa-db-fra.com

NSUserDefaults - Comment savoir si une clé existe

Je travaille sur une petite application iPhone et j'utilise NSUserDefaults comme persistance de mes données. Il suffit de noter quelques éléments, tels que des noms et des chiffres, pour que je puisse aussi bien garder les choses simples.

J'ai trouvé cette page pour une référence, mais je ne pense pas que cela puisse répondre à ma question. En gros, je veux pouvoir vérifier si une valeur (ou une clé) existe déjà dans le NSUserDefaults, puis faire quelque chose en conséquence.

Quelques exemples: L’application démarre. Si c’est la première fois qu’elle démarre, elle émet une alerte disant bienvenue. Pour dire si c'est la première fois qu'il est ouvert, il lit le UserDefaults et vérifie.

Exemple 2: Il est écrit "Bonjour [Nom]", où Nom est quelque chose que vous avez entré. Si vous avez ouvert l'application et qu'il n'y a pas de nom, le nom "Hello World" devrait s'afficher. Je dois vérifier si vous avez déjà entré un nom et agir en conséquence. Le nom serait stocké dans NSUserDefaults.

Un peu d'aide ici? Je l'apprécierais vraiment!

202
Ethan Mick

objectForKey: retournera nil s'il n'existe pas.

376
jspcal

Comme mentionné ci-dessus, cela ne fonctionnera pas pour les types primitifs où 0/NO pourrait être une valeur valide. J'utilise ce code.

NSUserDefaults *defaults= [NSUserDefaults standardUserDefaults];
if([[[defaults dictionaryRepresentation] allKeys] containsObject:@"mykey"]){

    NSLog(@"mykey found");
}
93
i.jameelkhan

Le objectForKey: La méthode retournera nil si la valeur n’existe pas. Voici un simple test IF/THEN qui vous indiquera si la valeur est nulle:

if([[NSUserDefaults standardUserDefaults] objectForKey:@"YOUR_KEY"] != nil) {
    ...
}
54
mirap

"objectForKey retournera nil s'il n'existe pas." Il renverra également nil s'il existe et qu'il s'agisse d'un entier ou d'un booléen avec une valeur nulle (c'est-à-dire FALSE ou NO pour le booléen).

J'ai testé cela dans le simulateur pour 5.1 et 6.1. Cela signifie que vous ne pouvez pas vraiment tester si des entiers ou des booléens ont été définis en demandant "l'objet". Vous pouvez vous en tirer avec des nombres entiers si cela ne vous dérange pas de traiter "non défini" comme s'il était "défini sur zéro".

Les personnes qui ont déjà testé cela semblent avoir été trompées par l'aspect faux négatif, c'est-à-dire en vérifiant si objectForKey renvoie nil lorsque vous savez que la clé n'a pas été définie, mais en omettant de remarquer qu'il le renvoie également si la clé a été définie. défini mais a été réglé sur NO.

Pour mon propre problème, cela m'a envoyé ici, je viens de finir par changer la sémantique de mon booléen afin que ma valeur par défaut soit conforme à la valeur définie sur NO. Si ce n'est pas une option, vous devrez enregistrer comme autre chose qu'un booléen et assurez-vous que vous pouvez faire la différence entre OUI, NON et "non défini".

6
JamesKVL

Swift 3/4:

Voici une extension simple pour les types valeur-clé Int/Double/Float/Bool qui imitent le comportement de retour facultatif des autres types accessibles via UserDefaults.

(Editer le 30 août 2018: Mis à jour avec une syntaxe plus efficace issue de la suggestion de Leo.)

extension UserDefaults {
    /// Convenience method to wrap the built-in .integer(forKey:) method in an optional returning nil if the key doesn't exist.
    func integerOptional(forKey: String) -> Int? {
        return self.object(forKey: forKey) as? Int
    }
    /// Convenience method to wrap the built-in .double(forKey:) method in an optional returning nil if the key doesn't exist.
    func doubleOptional(forKey: String) -> Double? {
        return self.object(forKey: forKey) as? Double
    }
    /// Convenience method to wrap the built-in .float(forKey:) method in an optional returning nil if the key doesn't exist.
    func floatOptional(forKey: String) -> Float? {
        return self.object(forKey: forKey) as? Float
    }
    /// Convenience method to wrap the built-in .bool(forKey:) method in an optional returning nil if the key doesn't exist.
    func boolOptional(forKey: String) -> Bool? {
        return self.object(forKey: forKey) as? Bool
    }
}

Elles sont maintenant plus cohérentes avec les autres méthodes get intégrées (chaîne, données, etc.). Utilisez simplement les méthodes get à la place des anciennes.

let AppDefaults = UserDefaults.standard

// assuming the key "Test" does not exist...

// old:
print(AppDefaults.integer(forKey: "Test")) // == 0
// new:
print(AppDefaults.integerOptional(forKey: "Test")) // == nil
4
stef

Étendez UserDefaults une fois pour ne pas copier-coller cette solution:

extension UserDefaults {

    func hasValue(forKey key: String) -> Bool {
        return nil != object(forKey: key)
    }
}

// Example
UserDefaults.standard.hasValue(forKey: "username")
3
mbelsky

Version rapide pour obtenir Bool?

NSUserDefaults.standardUserDefaults().objectForKey(DefaultsIsGiver) as? Bool
3
Ben

Essayez cette petite crumpet:

-(void)saveUserSettings{
NSNumber*   value;

value = [NSNumber numberWithFloat:self.sensativity];
[[NSUserDefaults standardUserDefaults] setObject:value forKey:@"sensativity"];
}
-(void)loadUserSettings{
    NSNumber*   value;
    value = [[NSUserDefaults standardUserDefaults] objectForKey:@"sensativity"];
    if(value == nil){
        self.sensativity = 4.0;
    }else{
        self.sensativity = [value floatValue];
    }
}

Traiter tout comme un objet. Semble travailler pour moi.

3
pepelkod

Je viens de traverser cela, et toutes de vos réponses m'ont aidé à trouver une bonne solution, pour moi. J'ai résisté à l'itinéraire suggéré par, juste parce que j'avais du mal à lire et à comprendre.

Voici ce que j'ai fait. J'ai eu un BOOL étant transporté dans une variable appelée "_talkative".

Lorsque je définis mon objet (NSUserDefaults) par défaut, je le fixe comme n objet, comme je pouvais alors tester pour voir s'il était nil:

//converting BOOL to an object so we can check on nil
[defaults setObject:@(_talkative) forKey:@"talkative"];

Ensuite, quand je suis allé voir s'il existait, j'ai utilisé:

if ([defaults objectForKey:@"talkative"]!=nil )
  {

Ensuite, j'ai utilisé l'objet comme un BOOL:

if ([defaults boolForKey:@"talkative"]) {
 ...

Cela semble fonctionner dans mon cas. Cela me faisait plus de sens visuel.

2
james Burns

Dans Swift3, j'ai utilisé de cette façon

var hasAddedGeofencesAtleastOnce: Bool {
    get {
        return UserDefaults.standard.object(forKey: "hasAddedGeofencesAtleastOnce") != nil
    }
}

Le réponse est génial si vous devez l'utiliser plusieurs fois.

J'espère que ça aide :)

0
Nikhil Manapure