Devo verificare se un dict ha una chiave o meno. Come?
NSDictionarycontiene un tasto qualsiasi (non specifico) si dovrebbe usare [dictionary allKeys].count == 0Se l' countè 0non ci sono chiavi nel NSDictionary.
Devo verificare se un dict ha una chiave o meno. Come?
NSDictionarycontiene un tasto qualsiasi (non specifico) si dovrebbe usare [dictionary allKeys].count == 0Se l' countè 0non ci sono chiavi nel NSDictionary.
Risposte:
objectForKey restituirà zero se non esiste una chiave.
[NSNull null]invece.
if ([[dictionary allKeys] containsObject:key]) {
// contains key
}
o
if ([dictionary objectForKey:key]) {
// contains object
}
Le versioni più recenti di Objective-C e Clang hanno una sintassi moderna per questo:
if (myDictionary[myKey]) {
}
Non è necessario verificare l'uguaglianza con zero, poiché solo gli oggetti Objective-C non nulli possono essere memorizzati in dizionari (o matrici). E tutti gli oggetti Objective-C sono valori di verità. Anche @NO, @0e [NSNull null]valutare come vero.
Modifica: Swift ora è una cosa.
Per Swift proveresti qualcosa di simile al seguente
if let value = myDictionary[myKey] {
}
Questa sintassi eseguirà il blocco if solo se myKey è nel dict e se lo è, il valore viene archiviato nella variabile value. Nota che questo funziona anche con valori falsi come 0.
if ([mydict objectForKey:@"mykey"]) {
// key exists.
}
else
{
// ...
}
Quando si utilizzano i dizionari JSON:
#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]
if( isNull( dict[@"my_key"] ) )
{
// do stuff
}
Mi piace la risposta di Fernandes anche se tu chiedi l'obj due volte.
Questo dovrebbe anche fare (più o meno lo stesso della A di Martin).
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 e questa risposta funzionano entrambi su iPad2 iOS 5.0.1 9A405
Un gotcha molto brutto che ha appena perso un po 'del mio tempo nel debug: potresti trovarti spinto dal completamento automatico per provare a usare quello doesContainche sembra funzionare.
Ad eccezione, doesContainutilizza un confronto ID anziché il confronto hash utilizzato da objectForKeyquindi se si dispone di un dizionario con chiavi stringa, restituirà NO a 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
Sì. Questo tipo di errori sono molto comuni e portano al crash dell'app. Quindi io uso per aggiungere NSDictionary in ogni progetto come di seguito:
//.h codice file:
@interface NSDictionary (AppDictionary)
- (id)objectForKeyNotNull : (id)key;
@end
Il codice del file //.m è il seguente
#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
Nel codice è possibile utilizzare come di seguito:
NSStrting *testString = [dict objectForKeyNotNull:@"blah"];
Per verificare l'esistenza della chiave in NSDictionary:
if([dictionary objectForKey:@"Replace your key here"] != nil)
NSLog(@"Key Exists");
else
NSLog(@"Key not Exists");
Perché zero non può essere archiviato nelle strutture di dati di Foundation a NSNullvolte significa rappresentare un nil. Poiché NSNullè un oggetto singleton, puoi verificare se NSNullè il valore memorizzato nel dizionario utilizzando il confronto puntatore diretto:
if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }
NSNullistanza singleton è stata memorizzata nel dizionario come valore per la chiave @"myKey". È una cosa totalmente diversa dal fatto che la chiave @"myKey"non si trova nel dizionario - in effetti i due si escludono a vicenda.
Soluzione per rapido 4.2
Quindi, se vuoi solo rispondere alla domanda se il dizionario contiene la chiave, chiedi:
let keyExists = dict[key] != nil
Se vuoi il valore e sai che il dizionario contiene la chiave, dì:
let val = dict[key]!
Ma se, come al solito, non sai che contiene la chiave - vuoi prenderla e usarla, ma solo se esiste - usa qualcosa come if let:
if let val = dict[key] {
// now val is not nil and the Optional has been unwrapped, so use it
}
Ti suggerirei di archiviare il risultato della ricerca in una variabile temp, verificare se la variabile temp è nulla e quindi utilizzarla. In questo modo non guardi lo stesso oggetto due volte:
id obj = [dict objectForKey:@"blah"];
if (obj) {
// use obj
} else {
// Do something else
}
Come Adirael ha suggerito objectForKeydi controllare l'esistenza dei tasti ma quando si chiama objectForKeynel dizionario nullable, l'app si blocca, quindi ho risolto il problema nel modo seguente.
- (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"
}