I found this answer:
https://stackoverflow.com/a/5163334/1364174
Which presents how for in
loop is implemented.
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 have Automatic Reference Counting (ARC) turned on, you got an error
Sending '__strong id *' to parameter of type '__unsafe_unretained_id*' changes retain/release properties of pointer
But even when I turn ARC off I found out that I __object array seems to behave strangely :
This is actual Code (I assumed MAX_STACKBUFF_SIZE to be 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 the __object array. I also found out that when you try to iterate through __enumState.itemsPtr it actually works.
Could you explain me what is going on here ? Why my __objects
seems to be "shrunken down". And why it doesn't contains desired object? And why is that error when ARC is turned on.
Thank you very very much in advance for your time and effort! (I provided screenshot for better understanding what causes an error)
First of all, strong pointers cannot be used in C-structures, as explained in the "Transitioning to ARC Release Notes", therefore the objects array has be be declared as
if you compile with ARC.
Now it is not obvious (to me) from the
NSFastEnumeration
documentation, but it is explained in Cocoa With Love:Implementing countByEnumeratingWithState:objects:count: that the implementation need not fill the supplied objects array, but can just set__enumState.itemsPtr
to an existing array (e.g. some internal storage). In that case, the contents of the__objects
array is undefined, which causes the crash.Replacing
by
gives the expected result, which is what you observed.
Another reference can be found in the "FastEnumerationSample" sample code: