Je dois vérifier si un dict a une clé ou non. Comment?
objectForKey
retournera nil si une clé n'existe pas.
if ([[dictionary allKeys] containsObject:key]) {
// contains key
}
ou
if ([dictionary objectForKey:key]) {
// contains object
}
Les versions plus récentes d'Objective-C et de Clang ont une syntaxe moderne pour cela:
if (myDictionary[myKey]) {
}
Il n'est pas nécessaire de vérifier l'égalité avec nil, car seuls les objets Objective-C non nuls peuvent être stockés dans des dictionnaires (ou des tableaux). Et tous les objets Objective-C sont des valeurs de vérité. Même @NO
, @0
et [NSNull null]
sont considérés comme vrais.
Edit: Swift est maintenant une chose.
Pour Swift, essayez quelque chose comme ce qui suit
if let value = myDictionary[myKey] {
}
Cette syntaxe n'exécutera le bloc if que si myKey est dans le dict, et si c'est le cas, la valeur est stockée dans la variable de valeur. Notez que cela fonctionne même pour les valeurs de Falsey telles que 0.
if ([mydict objectForKey:@"mykey"]) {
// key exists.
}
else
{
// ...
}
Lors de l'utilisation de dictionnaires JSON:
#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]
if( isNull( dict[@"my_key"] ) )
{
// do stuff
}
J'aime la réponse de Fernandes même si vous demandez deux fois l'obj.
Cela devrait également faire (plus ou moins la même chose que Martin A).
id obj;
if ((obj=[dict objectForKey:@"blah"])) {
// use obj
} else {
// Do something else like creating the obj and add the kv pair to the dict
}
Martin et cette réponse fonctionnent tous les deux sur iPad2 iOS 5.0.1 9A405
Un casse-tête très méchant qui a juste fait perdre un peu de mon temps au débogage - vous pouvez être amené par l'auto-complétion à essayer d'utiliser doesContain
qui semble fonctionner.
Excepté, doesContain
utilise une comparaison d'identifiant au lieu de la comparaison de hachage utilisée par objectForKey
. Ainsi, si vous avez un dictionnaire avec des clés de chaîne, il retournera NON à doesContain
.
NSMutableDictionary* keysByName = [[NSMutableDictionary alloc] init];
keysByName[@"fred"] = @1;
NSString* test = @"fred";
if ([keysByName objectForKey:test] != nil)
NSLog(@"\nit works for key lookups"); // OK
else
NSLog(@"\nsod it");
if (keysByName[test] != nil)
NSLog(@"\nit works for key lookups using indexed syntax"); // OK
else
NSLog(@"\nsod it");
if ([keysByName doesContain:@"fred"])
NSLog(@"\n doesContain works literally");
else
NSLog(@"\nsod it"); // this one fails because of id comparison used by doesContain
Oui. Ce type d'erreur est très courant et conduit à un crash de l'application. J'utilise donc pour ajouter NSDictionary à chaque projet comme ci-dessous:
code du fichier //.h:
@interface NSDictionary (AppDictionary)
- (id)objectForKeyNotNull : (id)key;
@end
//.m code du fichier est comme ci-dessous
#import "NSDictionary+WKDictionary.h"
@implementation NSDictionary (WKDictionary)
- (id)objectForKeyNotNull:(id)key {
id object = [self objectForKey:key];
if (object == [NSNull null])
return nil;
return object;
}
@end
Dans le code, vous pouvez utiliser comme ci-dessous:
NSStrting *testString = [dict objectForKeyNotNull:@"blah"];
En utilisant Swift, ce serait:
if myDic[KEY] != nil {
// key exists
}
Étant donné que nil ne peut pas être stocké dans les structures de données Foundation, NSNull
représente parfois une nil
. Étant donné que NSNull
est un objet singleton, vous pouvez vérifier si NSNull
est la valeur stockée dans le dictionnaire à l'aide de la comparaison directe de pointeur:
if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }
Pour vérifier l'existence de la clé dans NSDictionary:
if([dictionary objectForKey:@"Replace your key here"] != nil)
NSLog(@"Key Exists");
else
NSLog(@"Key not Exists");
Je vous suggérerais de stocker le résultat de la recherche dans une variable temporaire, de vérifier si la variable temporaire est nulle et de l'utiliser. De cette façon, vous ne regardez pas le même objet deux fois:
id obj = [dict objectForKey:@"blah"];
if (obj) {
// use obj
} else {
// Do something else
}
Comme Adirael a suggéré à objectForKey
de vérifier l’existence de clés, mais lorsque vous appelez objectForKey
dans le dictionnaire nullable, l’application se bloque et j’ai corrigé le problème de la manière suivante.
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;
if (dictionary && (object != [NSNull null])) {
self.name = [dictionary objectForKey:@"name"];
self.age = [dictionary objectForKey:@"age"];
}
return self;
}
if ([MyDictionary objectForKey:MyKey]) {
// "Key Exist"
}
Solution pour Swift 4.2
Donc, si vous voulez juste répondre à la question de savoir si le dictionnaire contient la clé, demandez:
let keyExists = dict[key] != nil
Si vous voulez la valeur et que vous savez que le dictionnaire contient la clé, dites:
let val = dict[key]!
Mais si, comme cela se produit habituellement, vous ne savez pas qu'elle contient la clé - vous voulez la récupérer et l'utiliser, mais seulement si elle existe - utilisez quelque chose comme if let
:
if let val = dict[key] {
// now val is not nil and the Optional has been unwrapped, so use it
}