Muszę sprawdzić, czy dykt ma klucz, czy nie. W jaki sposób?
NSDictionary
zawiera żadnego klucza (niespecyficzna) należy użyć [dictionary allKeys].count == 0
Jeśli count
to 0
nie istnieją żadne klucze w NSDictionary
.
Muszę sprawdzić, czy dykt ma klucz, czy nie. W jaki sposób?
NSDictionary
zawiera żadnego klucza (niespecyficzna) należy użyć [dictionary allKeys].count == 0
Jeśli count
to 0
nie istnieją żadne klucze w NSDictionary
.
Odpowiedzi:
objectForKey
zwróci zero, jeśli klucz nie istnieje.
[NSNull null]
zamiast tego.
if ([[dictionary allKeys] containsObject:key]) {
// contains key
}
lub
if ([dictionary objectForKey:key]) {
// contains object
}
Nowsze wersje Objective-C i Clang mają do tego nowoczesną składnię:
if (myDictionary[myKey]) {
}
Nie musisz sprawdzać równości z wartością zero, ponieważ tylko słowniki Objective-C inne niż zero mogą być przechowywane w słownikach (lub tablicach). Wszystkie obiekty Objective-C są prawdziwymi wartościami. Nawet @NO
, @0
i [NSNull null]
ocenić, jak prawdziwe.
Edycja: Swift jest teraz rzeczą.
W przypadku Swift wypróbujesz coś takiego
if let value = myDictionary[myKey] {
}
Ta składnia wykona blok if tylko wtedy, gdy myKey znajduje się w dykcie, a jeśli tak, to wartość jest przechowywana w zmiennej wartości. Zauważ, że działa to nawet dla wartości falsey, takich jak 0.
if ([mydict objectForKey:@"mykey"]) {
// key exists.
}
else
{
// ...
}
Podczas korzystania ze słowników JSON:
#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]
if( isNull( dict[@"my_key"] ) )
{
// do stuff
}
Podoba mi się odpowiedź Fernandesa, mimo że dwukrotnie pytasz o obiekt.
Powinno to również zrobić (mniej więcej to samo, co Martin's 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 i ta odpowiedź działają zarówno na iPadzie2 iOS 5.0.1 9A405
Jedna bardzo nieprzyjemna gotcha, która zmarnowała trochę mojego czasu na debugowanie - może pojawić się monit o automatyczne uzupełnianie, aby spróbować użyć tego, doesContain
co wydaje się działać.
Z wyjątkiem tego, że doesContain
używa porównania id zamiast porównania skrótu używanego przezobjectForKey
więc jeśli masz słownik z kluczami łańcuchowymi, to zwróci NIE do 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
Tak. Tego rodzaju błędy są bardzo częste i prowadzą do awarii aplikacji. Używam więc, aby dodać NSDictionary do każdego projektu, jak poniżej:
Kod pliku //.h:
@interface NSDictionary (AppDictionary)
- (id)objectForKeyNotNull : (id)key;
@end
Kod pliku //.m jest jak poniżej
#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
W kodzie możesz użyć, jak poniżej:
NSStrting *testString = [dict objectForKeyNotNull:@"blah"];
Aby sprawdzić istnienie klucza w NSDictionary:
if([dictionary objectForKey:@"Replace your key here"] != nil)
NSLog(@"Key Exists");
else
NSLog(@"Key not Exists");
Ponieważ zero nie może być przechowywane w strukturach danych Fundacji, NSNull
czasami ma reprezentować nil
. Ponieważ NSNull
jest to obiekt singletonowy, możesz sprawdzić, czy NSNull
wartość jest przechowywana w słowniku, używając bezpośredniego porównania wskaźnika:
if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }
NSNull
instancja singletonu została zapisana w słowniku jako wartość klucza @"myKey"
. To zupełnie inna sprawa niż klucz, którego @"myKey"
nie ma w słowniku - w istocie oba się wykluczają.
Rozwiązanie dla szybkiego 4.2
Jeśli więc chcesz tylko odpowiedzieć na pytanie, czy słownik zawiera klucz, zapytaj:
let keyExists = dict[key] != nil
Jeśli chcesz tę wartość i wiesz, że słownik zawiera klucz, powiedz:
let val = dict[key]!
Ale jeśli, jak to zwykle bywa, nie wiesz, że zawiera on klucz - chcesz go pobrać i użyć, ale tylko jeśli istnieje - użyj czegoś takiego if let
:
if let val = dict[key] {
// now val is not nil and the Optional has been unwrapped, so use it
}
Sugeruję zapisanie wyniku wyszukiwania w zmiennej temp, przetestowanie, czy zmienna temp jest zerowa, a następnie użycie jej. W ten sposób nie spojrzysz dwukrotnie na ten sam obiekt:
id obj = [dict objectForKey:@"blah"];
if (obj) {
// use obj
} else {
// Do something else
}
Jak Adirael zasugerował, objectForKey
aby sprawdzić kluczową egzystencję, ale kiedy wywołujesz objectForKey
słownik zerowy, aplikacja ulega awarii, więc naprawiłem to w następujący sposób.
- (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"
}