How inside a loop works inside - Objective C - Foundation

I found this answer:

stack overflow

What is a for in loop.

 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]; } } 

The problem is that I found it wrong.

First of all, when you turned on automatic link counting (ARC), you received an error message

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

Screenshots of an error

But even when I turn off ARC, I found that the array of __ objects seems weird:

Screenshot of error2

This is the actual code (I assumed MAX_STACKBUFF_SIZE is 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; 

I got EXC_BAD_ACESS when I try to get the contents of an array of __ objects. I also found out that when you try to iterate through __enumState.itemsPtr, it really works.

Could you explain to me what is going on here? Why __objects my __objects seem "crumpled". And why does it not contain the desired object? And why this error when turning on ARC.

Thank you very well in advance for your time and efforts! (I presented a screenshot to better understand what causes the error)

+5
source share
1 answer

First of all, strong pointers cannot be used in C-structures, as described in the "Transition to ARC Release Notes" section, so an array of objects will be declared as

 __unsafe_unretained id __objects[MAX_STACKBUFF_SIZE]; 

if you compile ARC.

Now this is not obvious (to me) from the NSFastEnumeration documentation, but it is explained in Cocoa With love: implementation of countByEnumeratingWithState: objects: count: that the implementation should not fill the array of supplied objects, but can simply set __enumState.itemsPtr to an existing array (for example, to some internal storage). In this case, the contents of the __objects array is undefined, resulting in a failure.

Replacement

 id obj = __objects[i]; 

by

 id obj = __enumState.itemsPtr[i]; 

gives the expected result that you observed.

Another link can be found in the "FastEnumerationSample" sample code:

When implementing this method, you have two options:

1) Use the stack based array provided by stackbuf. If you do this, then you must respect the value of len.

2) Return your own array of objects. If you do this, return the entire length of the array returned until you finish the objects, then return 0. For example, the associated implementation array can return each array in order, until you repeat through all arrays.

In any case state->itemsPtr MUST be a valid array (non-nil) ....

+3
source

All Articles