2011-12-14 15 views
34

¿Cuáles son las ventajas y desventajas de los dos métodos siguientes:Objective-C enumerateUsingBlock versus enumeración rápida?

enumerateUsingBlock

NSArray *myArray = [[NSArray alloc] init]; 
[myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) { 
    if (anObject == someOtherObject) { 
     [anObject doSomething:idx]; 
     *stop = YES; 
    } 
}]; 

enumeración rápida

NSArray *myArray = [[NSArray alloc] init]; 
int idx = 0 
for (id anObject in myArray) { 
    if (anObject == someOtherObject) { 
     [anObject doSomething:idx]; 
     break; 
    } 
    ++idx; 
} 
+2

Para su información, tanto IFS tienen malas errores tipográficos - cabe en lugar de == = –

+0

duplicado posible de [Al utilizar enumerateObjectsUsingBlock frente a] (http: // desbordamiento de pila.com/questions/4486622/when-to-use-enumerateobjectsusingblock-vs-for) –

Respuesta

47

This blog post cubre las principales diferencias. En resumen:

  • enumeración rápida está disponible en OS X 10.5 +, los bloques están disponibles en 10.6+
  • Por simple enumeración, rápida enumeración es un poco más rápido que la enumeración basada en bloques
  • Es más fácil (y más rendimiento) para hacer una enumeración concurrente o inversa con enumeración basada en bloques que con enumeración rápida
  • Al enumerar a través de un NSDictionary puede obtener la clave y el valor de un golpe con un enumerador basado en bloques, mientras que con la enumeración rápida debe usar la clave para recuperar el valor en un mensaje de envío separado.

En cuanto al último punto (NSDictionary enumeración), comparar esto:

for (id key in dictionary) 
{ 
    id obj = [dictionary objectForKey: key]; 
    // do something with key and obj 
} 

a esto:

[dictionary enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { 
    // do something with key and obj 
}]; 

Además, ambos métodos de proteger las colecciones mutables de la mutación dentro del bucle de enumeración. Curiosamente, si intentas mutar la colección dentro de una enumeración basada en bloques, obtienes una excepción lanzada por CoreFoundation's __NSFastEnumerationMutationHandler, sugiriendo que hay algún código común bajo el capó.

NSMutableArray *myArray = [NSMutableArray arrayWithObjects:@"a", @"b", nil]; 
[myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) { 
    // Attempt to mutate the array during enumeration 
    [myArray addObject:@"c"]; 
}]; 

Salida:

2011-12-14 22:37:53.716 Untitled[5809:707] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x109614190> was mutated while being enumerated.' 
*** First throw call stack: 
(
    0 CoreFoundation      0x00007fff8cca7286 __exceptionPreprocess + 198 
    1 libobjc.A.dylib      0x00007fff8319ad5e objc_exception_throw + 43 
    2 CoreFoundation      0x00007fff8cd311dc __NSFastEnumerationMutationHandler + 172 
    3 CoreFoundation      0x00007fff8cc9efb4 __NSArrayEnumerate + 612 
    4 Untitled       0x00000001094efcea main + 250 
    5 Untitled       0x00000001094efbe4 start + 52 
    6 ???         0x0000000000000001 0x0 + 1 
) 
terminate called throwing an exceptionRun Command: line 1: 5809 Abort trap: 6   ./"$2" 
+0

Dejando de lado el rendimiento, ¿qué versión es más fácil de leer para los lectores? ¿a primera vista? –

+1

@rsanchezsaez ¡Interesante pregunta! Encuentro que un bucle 'for' sobre las teclas del diccionario es más legible. La sintaxis del bloque todavía no es intuitiva para mí. –

+0

para el valor clave, encuentro el bloque más intuitivo (vine de C (++) y solo usé el bloque una vez) –

4

primeros pensamientos que vienen a la mente

  • Los bloques están disponibles en iOS 4 y posteriores, por lo que si necesita admitir versiones anteriores, no podrá usar la sintaxis del bloque.

  • Son bastante equivalentes en términos de lo que hacen, aparte de que no se puede estropear accidentalmente el contador en la versión de bloque.

  • Otra diferencia de potencial es que puede definir el bloque en otro lugar y pasar bloques diferentes en función de su estado.

Espero que esto era sólo un ejemplo muy áspera como el fragmento de código es bastante pobre y hay manera más eficiente de hacerlo;)

+0

Además, si recuerdo bien, se indicó en un video de WWDC 2010 que la enumeración de bloques es aún más eficaz que la enumeración rápida. –

+1

Ese es el problema con los videos que sabes que hay cosas buenas ahí, pero que tengas suerte de encontrarlo nuevamente en el futuro. Miré los documentos para [Enumeración: atravesando los elementos de una colección] (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Enumerators.html) y no se destacó mención de un aumento en el rendimiento: S –

+2

En realidad, acabo de encontrarlo. Es el video "Novedades en la fundación para iOS 4" de 2010. –

Cuestiones relacionadas