para cada bucle en Objective-C para acceder al diccionario NSMutable

268

Me está resultando difícil acceder a claves y valores de diccionario mutables en Objective-C.

Supongamos que tengo esto:

NSMutableDictionary *xyz=[[NSMutableDictionary alloc] init];

Puedo establecer claves y valores. Ahora, solo quiero acceder a cada clave y valor, pero no sé la cantidad de claves configuradas.

En PHP es muy fácil, algo así:

foreach ($xyz as $key => $value)

¿Cómo es posible en Objective-C?

Sagar R. Kothari
fuente

Respuestas:

662
for (NSString* key in xyz) {
    id value = xyz[key];
    // do stuff
}

Esto funciona para todas las clases que se ajustan al protocolo NSFastEnumeration (disponible en 10.5+ y iOS), aunque NSDictionaryes una de las pocas colecciones que le permite enumerar claves en lugar de valores. Le sugiero que lea sobre la enumeración rápida en el Tema de programación de colecciones .

Sin embargo, debo agregar que NUNCA debes modificar una colección mientras la enumeras.

zneak
fuente
44
Me preguntaba, ¿no debería haber sido: for (NSString * key in [xyz allKeys]) ?? O realmente no importa.
FlowUI. SimpleUITesting.com
66
@ user76859403 Enumerar un diccionario, de hecho, enumera las claves. for (NSString* key in [xyz allKeys])es conceptualmente lo mismo.
zneak
Use [xyz allKeys] si necesita mutar el diccionario mientras enumera las claves. Vea mi respuesta a continuación.
Brody Robertson
¿Este bucle devuelve el mismo orden todo el tiempo? ¿O necesitamos otra forma de usarlo para las secciones de TableView?
ymutlu
1
@ymutlu, los diccionarios de cacao no están ordenados. Esto significa que el orden en que iteran puede cambiar cada vez que los modifique.
zneak
98

Solo para no dejar de lado la opción 10.6+ para enumerar claves y valores usando bloques ...

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

Si desea que las acciones sucedan simultáneamente:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];
Quinn Taylor
fuente
2
3 formas diferentes de enumerar a través de un diccionario. . . je, esto me recuerda la respuesta "Strangest Language Feature" donde VB tiene 7 tipos diferentes de bucles.
dreamlax
3
Bueno ... objectEnumerator se agregó en 1994, for for (... in ...) aproximadamente en 2006, y Blocks se agregaron en 2009. La forma de enumeración en bloque es una consecuencia natural.
bbum
Esto parece ser más rápido que el estándar para ... en construcción: oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration
lkraider
1
@lkraider, comenté en esa publicación, que en realidad compara la enumeración basada en bloques con un antiguo bucle for, no el for ... en construcción.
Quinn Taylor el
¿Para qué sirve *stop? ¿Cómo lo usas? Alguna referencia?
borisdiakur
13

Si necesita mutar el diccionario mientras enumera:

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}
Brody Robertson
fuente
El motivo es allKeysdevuelve una copia de las claves. Por lo tanto, es seguro mutar el diccionario.
Honghao Zhang
5

La forma más fácil de enumerar un diccionario es

for (NSString *key in tDictionary.keyEnumerator) 
{
    //do something here;
}

¿Dónde tDictionaryestá el NSDictionaryo NSMutableDictionaryquieres iterar?

Avinash
fuente
2

La enumeración rápida se agregó en 10.5 y en el sistema operativo iPhone, y es significativamente más rápido, no solo el azúcar sintáctico. Si tiene que apuntar al tiempo de ejecución anterior (es decir, 10.4 y hacia atrás), deberá usar el método anterior de enumeración:

NSDictionary *myDict = ... some keys and values ...
NSEnumerator *keyEnum = [myDict keyEnumerator];
id key;

while ((key = [keyEnum nextObject]))
{
    id value = [myDict objectForKey:key];
    ... do work with "value" ...
}

No libera el objeto enumerador y no puede restablecerlo. Si desea comenzar de nuevo, debe solicitar un nuevo objeto enumerador del diccionario.

dreamlax
fuente
1

Puede usar -[NSDictionary allKeys]para acceder a todas las teclas y recorrerlas.

gcamp
fuente
2
Es cierto, pero esto crea una matriz adicional autorrelegada, que puede ser bastante derrochadora, especialmente para diccionarios con muchas claves.
Quinn Taylor