2010-10-07 20 views
11

Parece de la experimentación que la expresión de colección se evalúa solo una vez. Considere este ejemplo:Objetivo c "para cada uno" (enumeración rápida) - evaluación de la colección?

static NSArray *a; 

- (NSArray *)fcn 
{ 
    if (a == nil) 
     a = [NSArray arrayWithObjects:@"one", @"two", @"three", nil]; 
    NSLog(@"called"); 
    return a; 
} 

... 

for (NSString *s in [self fcn]) 
    NSLog(@"%@", s); 

La salida es:

2010-10-07 07:37:31.419 WidePhotoViewer Lite[23694:207] called 
2010-10-07 07:37:31.420 WidePhotoViewer Lite[23694:207] one 
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] two 
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] three 

que indica que [libre FCN] se llama sólo una vez.

¿Alguien puede confirmar que este es el comportamiento especificado (en lugar de simplemente observado)?

Lo que tengo en mente es hacer algo como esto:

for (UIView *v in [innerView subviews]) { 

en lugar de esto:

NSArray *vs = [innerView subviews]; 
for (UIView *v in vs) { 

Pensamientos?

+0

Gracias a ellos, esp. Shmurk, que intentó responder ... esto de hecho arrojó algo de luz sobre el asunto. (Verificar una implementación para aclarar una especificación es peligroso. De todos modos, ya lo había hecho al preparar la pregunta.) –

Respuesta

13

Este tipo de bucle for se denomina "enumeración rápida" (consulte el objeto NSFastEnumeration). La documentación de Apple dice que en "para obj en expresión", la expresión produce un objeto que cumple con el protocolo NSFastEnumeration, así que supongo que ese es el comportamiento correcto: la función se llama una vez, un iterador se crea una vez y se usa en el ciclo.

0

Esto es parte del comportamiento de la enumeración rápida. Para obtener un conocimiento profundo de la implementación de la enumeración rápida, consulte esta publicación en el blog en NSBlog: Implementing Fast Enumeration.

3

El sentido común dicta que es de esa manera. Pero ya que no se indica directamente en la documentación enumeración rápida, ¿por qué no echar un vistazo al propio protocolo:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSFastEnumeration_protocol/Reference/NSFastEnumeration.html

Este protocolo no está proporcionando métodos como nextObject o objectAtIndex, o algo parecido eso, pero en su lugar solicita una matriz C de objetos, sobre la cual se itera.

Aunque hay indicaciones sólidas, ningún documento garantiza que la expresión solo se evalúe una vez.

7

En la práctica, collection solo se evalúa una vez, puede verificar la fuente de clang, por ejemplo. Cuando la documentación no dice las cosas lo suficientemente precisas, debe confiar en la implementación.

Sí, creo que Apple debería aclarar la documentación. Por favor presenta un error, Marc!

Una manera pedante de conseguir esto es leer el margen de la documentación oficial, que se puede encontrar here. Se indica que

el enumerador tiene un protector de mutación por lo que si intenta modificar la recopilación durante la enumeración, se genera una excepción. Como está prohibida la mutación del objeto durante la iteración, puede realizar varias enumeraciones al mismo tiempo.

modo, la colección sobre la que itera no puede cambiar de todos modos.No dice si se evalúa en collection

for(id obj in collection) { ... } 

una o dos veces, el objeto resultante no puede cambiar.

+0

+1 solo por sugerir un archivo de errores. – Wevah

Cuestiones relacionadas