objective-c - how - swift cocoa
¿Cómo verificar si un NSDictionary o NSMutableDictionary contiene una clave? (14)
Necesito comprobar si un dict tiene una llave o no. ¿Cómo?
Como Adirael sugirió objectForKey
para verificar la existencia de la clave, pero cuando llama a objectForKey
en un diccionario que puede objectForKey
, la aplicación se objectForKey
, por lo que lo arreglé de la siguiente manera.
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;
if (dictionary && (object != [NSNull null])) {
self.name = [dictionary objectForKey:@"name"];
self.age = [dictionary objectForKey:@"age"];
}
return self;
}
Cuando se usan diccionarios JSON:
#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]
if( isNull( dict[@"my_key"] ) )
{
// do stuff
}
Debido a que nil no se puede almacenar en las estructuras de datos de Foundation, NSNull
veces representa un nil
. Debido a que NSNull
es un objeto singleton, puede verificar si NSNull
es el valor almacenado en el diccionario mediante la comparación directa de punteros:
if ((NSNull *)[user objectForKey:@"myKey"] == [NSNull null]) { }
Las versiones más recientes de Objective-C y Clang tienen una sintaxis moderna para esto:
if (myDictionary[myKey]) {
}
No es necesario verificar la igualdad con cero, ya que solo los objetos Objective-C que no sean nulos se pueden almacenar en diccionarios (o matrices). Y todos los objetos de Objective-C son valores de verdad. Incluso @NO
, @0
y [NSNull null]
evalúan como verdaderos.
Edit: Swift es ahora una cosa.
Para Swift intentarías algo como lo siguiente
if let value = myDictionary[myKey] {
}
Esta sintaxis solo ejecutará el bloque if si myKey está en el dict y si lo está, el valor se almacena en la variable de valor. Tenga en cuenta que esto funciona incluso para valores falsey como 0.
Le sugiero que almacene el resultado de la búsqueda en una variable temporal, compruebe si la variable temporal es nula y luego la utilice. De esa manera no se ve el mismo objeto dos veces:
id obj = [dict objectForKey:@"blah"];
if (obj) {
// use obj
} else {
// Do something else
}
Me gusta la respuesta de Fernandes, aunque pides el obj dos veces.
Esto también debería hacer (más o menos lo mismo que A de 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 y esta respuesta funcionan en iPad2 iOS 5.0.1 9A405
Para verificar la existencia de clave en NSDictionary:
if([dictionary objectForKey:@"Replace your key here"] != nil)
NSLog(@"Key Exists");
else
NSLog(@"Key not Exists");
Sí. Este tipo de errores son muy comunes y conducen a la caída de la aplicación. Así que uso para agregar NSDictionary en cada proyecto de la siguiente manera:
//.h código de archivo:
@interface NSDictionary (AppDictionary)
- (id)objectForKeyNotNull : (id)key;
@end
El código del archivo //.m es el siguiente
#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
En el código se puede utilizar de la siguiente manera:
NSStrting *testString = [dict objectForKeyNotNull:@"blah"];
Un error muy desagradable que solo desperdició un poco de mi tiempo en la depuración. Es posible que el autocompletar te pida que intentes usar doesContain
que parece funcionar.
Excepto, doesContain
utiliza una comparación de id en lugar de la comparación de hash utilizada por objectForKey
por lo que si tiene un diccionario con claves de cadena, devolverá NO a la 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
Usando Swift, sería:
if myDic[KEY] != nil {
// key exists
}
objectForKey
devolverá nil si no existe una clave.
if ([MyDictionary objectForKey:MyKey]) {
// "Key Exist"
}
if ([[dictionary allKeys] containsObject:key]) {
// contains key
}
o
if ([dictionary objectForKey:key]) {
// contains object
}
if ([mydict objectForKey:@"mykey"]) {
// key exists.
}
else
{
// ...
}