[objective-c] Cuándo usar enumerateObjectsUsingBlock vs. for



Answers

Para la enumeración simple, simplemente usar la enumeración rápida (es decir, un bucle for…in… ) es la opción más idiomática. El método de bloque puede ser marginalmente más rápido, pero eso no importa mucho en la mayoría de los casos: pocos programas están vinculados a la CPU, e incluso entonces es raro que el bucle en sí en lugar del cálculo interno sea un cuello de botella.

Un bucle simple también lee más claramente. Aquí está el modelo de las dos versiones:

for (id x in y){
}

[y enumerateObjectsUsingBlock:^(id x, NSUInteger index, BOOL *stop){
}];

Incluso si agrega una variable para seguir el índice, el bucle simple es más fácil de leer.

Entonces, cuando deberías usar enumerateObjectsUsingBlock: :? Cuando está almacenando un bloque para ejecutarlo más tarde o en varios lugares. Es bueno para cuando realmente está usando un bloque como una función de primera clase en lugar de un reemplazo sobreexplotado para un cuerpo de bucle.

Question

Además de las diferencias obvias:

  • Use enumerateObjectsUsingBlock cuando necesite el índice y el objeto
  • No use enumerateObjectsUsingBlock cuando necesite modificar las variables locales (me equivoqué al respecto, vea la respuesta de bbum)

¿En general, el elemento enumerateObjectsUsingBlock se considera mejor o peor cuando for (id obj in myArray) también funciona? ¿Cuáles son las ventajas / desventajas (por ejemplo, es más o menos rendimiento)?




Gracias a @bbum y @Chuck para comenzar comparaciones exhaustivas sobre el rendimiento. Me alegra saber que es trivial. Parece que he ido con:

  • for (... in ...) - como mi predeterminado goto. Más intuitivo para mí, más historia de programación aquí que cualquier preferencia real: reutilización de lenguaje cruzado, menos tipeo para la mayoría de las estructuras de datos debido a IDE autocompletado: P.

  • enumerateObject... - cuando se necesita acceso a objeto e índice. Y al acceder a estructuras que no sean de matriz o de diccionario (preferencia personal)

  • for (int i=idx; i<count; i++) - para matrices, cuando necesito comenzar en un índice distinto de cero




Para responder a la pregunta sobre el rendimiento, hice algunas pruebas con mi proyecto de prueba de rendimiento . Quería saber cuál de las tres opciones para enviar un mensaje a todos los objetos en una matriz es la más rápida.

Las opciones fueron:

1) makeObjectsPerformSelector

[arr makeObjectsPerformSelector:@selector(_stubMethod)];

2) enumeración rápida y envío regular de mensajes

for (id item in arr)
{
    [item _stubMethod];
}

3) enumerateObjectsUsingBlock y envío regular de mensajes

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
 {
     [obj _stubMethod];
 }];

Resultó que makeObjectsPerformSelector fue el más lento de lejos. Tomó el doble de tiempo que una enumeración rápida. Y enumerateObjectsUsingBlock fue el más rápido, fue alrededor de 15-20% más rápido que la iteración rápida.

Entonces, si está muy preocupado por el mejor rendimiento posible, use enumerateObjectsUsingBlock. Pero tenga en cuenta que, en algunos casos, el tiempo que toma enumerar una colección queda eclipsado por el tiempo que lleva ejecutar el código que desee que ejecute cada objeto.






Related