Cómo funciona el bucle interno internamente – Objetivo C – Fundación

Encontré esta respuesta:

https://stackoverflow.com/a/5163334/1364174

Que presenta cómo se implementa el bucle for in .

 NSFastEnumerationState __enumState = {0}; id __objects[MAX_STACKBUFF_SIZE]; NSUInteger __count; while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) { for (NSUInteger i = 0; i < __count; i++) { id obj = __objects[i]; [obj doSomething]; } } 

El problema es que lo encontré mal.

En primer lugar, cuando tiene el conteo automático de references (ARC) activado, tiene un error

Sending '__strong id *' to parameter of type '__unsafe_unretained_id*' changes retain/release properties of pointer

Captura de pantalla de un error

Pero incluso cuando apago el ARC, descubrí que __object de objects parece comportarse de manera extraña:

Captura de pantalla de error2

Este es el Código real (supuse que MAX_STACKBUFF_SIZE es 40):

 @autoreleasepool { NSArray *myArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; int MAX_STACKBUFF_SIZE = 40; NSFastEnumerationState __enumState = {0}; id __objects[MAX_STACKBUFF_SIZE]; NSUInteger __count; while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) { for (NSUInteger i = 0; i < __count; i++) { id obj = __objects[i]; __enumState.itemsPtr NSLog(@" Object from __objects ! %@", obj); // on screenshot different message } } } return 0; 

Obtuve EXC_BAD_ACESS cuando trato de get el contenido de la matriz __object. También descubrí que cuando intentas iterar a través de __enumState.itemsPtr, realmente funciona.

¿Podrías explicarme qué está pasando aquí? Por qué mis __objects parecen estar "networkingucidos". ¿Y por qué no contiene el object deseado? Y por qué es ese error cuando ARC está encendido.

¡Muchas gracias de antemano por su time y esfuerzo! (Proporcioné una captura de pantalla para comprender mejor qué causa un error)

En primer lugar, los pointers fuertes no pueden usarse en estructuras C, como se explica en la "Transición a las notas de la versión ARC", por lo tanto, la matriz de objects debe ser declarada como

 __unsafe_unretained id __objects[MAX_STACKBUFF_SIZE]; 

si comstacks con ARC.

Ahora no es obvio (para mí) de la documentation de NSFastEnumeration , pero se explica en Cocoa With Love: Implementación countByEnumeratingWithState: objects: count: que la implementación no necesita completar la matriz de objects suministrada, sino que simplemente puede establecer __enumState.itemsPtr en un matriz existente (por ejemplo, algún almacenamiento interno). En ese caso, el contenido de la matriz __objects no está definido, lo que provoca el locking.

Reemplazando

 id obj = __objects[i]; 

por

 id obj = __enumState.itemsPtr[i]; 

da el resultado esperado, que es lo que has observado.

Otra reference se puede encontrar en el código de muestra "FastEnumerationSample" :

Tiene dos opciones al implementar este método:

1) Utilice la matriz basada en stack proporcionada por stackbuf. Si haces esto, entonces debes respetar el valor de 'len'.

2) Devuelve tu propia variedad de objects. Si hace esto, devuelva la longitud completa de la matriz devuelta hasta que se quede sin objects, y luego devuelva 0. Por ejemplo, una implementación de matriz vinculada puede devolver cada matriz en order hasta que se repite en todas las matrices.

En cualquier caso, state->itemsPtr DEBE ser una matriz válida (no-nil). …