Devo verificare se un dict ha una chiave o meno. Come?
NSDictionary
contiene un tasto qualsiasi (non specifico) si dovrebbe usare [dictionary allKeys].count == 0
Se l' count
è 0
non ci sono chiavi nel NSDictionary
.
Devo verificare se un dict ha una chiave o meno. Come?
NSDictionary
contiene un tasto qualsiasi (non specifico) si dovrebbe usare [dictionary allKeys].count == 0
Se l' count
è 0
non 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
, @0
e [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 doesContain
che sembra funzionare.
Ad eccezione, doesContain
utilizza un confronto ID anziché il confronto hash utilizzato da objectForKey
quindi 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 NSNull
volte 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]) { }
NSNull
istanza 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 objectForKey
di controllare l'esistenza dei tasti ma quando si chiama objectForKey
nel 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"
}