220 votes

NSUserDefaults - Comment savoir si une clé existe

Je travaille sur une petite application iPhone, et j'utilise NSUserDefaults pour la persistance des données. Il ne doit garder la trace que de quelques éléments, tels que des noms et des nombres, alors je me suis dit qu'il valait mieux rester simple.

J'ai trouvé cette page à titre de référence, mais je ne pense pas qu'il puisse répondre à ma question. En gros, je veux pouvoir vérifier si une valeur (ou une clé) existe déjà dans le fichier NSUserDefaults et agir 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 savoir si c'est la première fois qu'elle s'ouvre, elle lit le fichier UserDefaults et les contrôles.

Exemple 2 : il dit "Hello [Name]", où Name est un nom que vous avez saisi. Si vous avez ouvert l'application et qu'il n'y a pas de nom, elle devrait dire "Hello World". Je dois vérifier si vous avez déjà saisi un nom et agir en conséquence. Le nom serait stocké dans NSUserDefaults .

Un peu d'aide ? J'apprécierais beaucoup !

402voto

jspcal Points 20715

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

1 votes

Je ne pense pas que l'on puisse stocker un type de données primitif dans le NSUserDefaults.

15 votes

La documentation d'Apple indique que "Si une valeur booléenne est associée à defaultName dans les valeurs par défaut de l'utilisateur, cette valeur est renvoyée. Sinon, NO est retourné". Je ne pense pas que la réponse ci-dessus soit correcte pour les BOOLs, vous ne pouvez pas déterminer s'il est défini NO ou s'il n'existe pas. Je pense qu'il faut utiliser – dictionaryRepresentation et vérifier la présence de la clé.

44 votes

@zekel Plutôt que de deviner, j'ai testé cela (sur iOS 5.1.1), et cela a détecté si un BOOL était présent ou non, indépendamment de ce que la valeur de ce BOOL pouvait être. "objectForKey" renvoie nil lorsque le BOOL n'est pas présent parce qu'il n'a jamais été défini.

110voto

i.jameelkhan Points 243

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

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

    NSLog(@"mykey found");
}

0 votes

Cela m'a sauvé. Je vous remercie !

0 votes

C'est la bonne réponse lorsqu'il s'agit de primitives telles que BOOL . Il permet de distinguer avec précision NO et n'est pas fixé, contrairement à objectForKey: .

0 votes

@devios1 - Si la clé est manquante, objectForKey: renverra nil indépendamment de l'intention du programmeur de stocker éventuellement un Bool ou tout autre type de données. Lorsqu'une primitive est présente, objectForKey: ne renvoie pas nil même si la clé est associée à une valeur primitive.

61voto

mirap Points 328

En objectForKey: renverra nil si la valeur n'existe pas. Voici un test IF / THEN simple qui vous dira si la valeur est nulle :

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

4voto

JamesKVL Points 21

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

J'ai testé cela dans le simulateur pour les versions 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 sortir pour les entiers si cela ne vous dérange pas de traiter "not set" comme s'il s'agissait de "set to zero".

Les personnes qui ont déjà testé cela semblent avoir été trompées par l'aspect faussement négatif, c'est-à-dire qu'elles ont testé cela en voyant si objectForKey renvoie nil lorsque vous savez que la clé n'a pas été définie, mais n'ont pas remarqué qu'il renvoie également nil si la clé a été définie, mais qu'elle a été définie à NO.

Pour mon propre problème, qui m'a amené ici, j'ai fini par changer la sémantique de mon booléen de façon à ce que la valeur par défaut souhaitée soit en accord avec la valeur fixée à NO. Si ce n'est pas possible, vous devrez stocker la valeur sous une forme autre qu'un booléen et vous assurer que vous pouvez faire la différence entre OUI, NON et "non défini".

0 votes

Je l'ai confirmé, mais il existe une solution simple : il suffit d'utiliser les nouveaux objets littéraux ou une expression encadrée. @0 au lieu de 0 , @NO au lieu de NO ou simplement @(variable) . Pour en savoir plus, cliquez ici.

2 votes

Object(forKey) sur des valeurs UserDefault d'entiers fixés à 0, et de Bools fixés à false, renverra correctement un résultat non nul. Si vous utilisez bool(forKey) pour tester si une valeur est définie, vous pouvez rencontrer des problèmes (parce que si la valeur est définie à False, bool(forKey) retournera 'false', même si vous attendez 'true').

3voto

pepelkod Points 36

Essayez ce petit 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. Cela semble fonctionner pour moi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X