Implement NSFastEnumerator: EXC_BAD_ACCESS on repeated execution for ... in

I have a data structure that I wanted to list. I tried to implement my NSFastEnumerator object as follows:

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id [])buffer count:(NSUInteger)len { NSUInteger c = 0; while (c < len) { id obj = [self objectAtIndex:state->state]; if (obj == nil) break; buffer[c] = obj; c++; state->state++; } state->itemsPtr = buffer; state->mutationsPtr = nil; return c; } 

If I use objectAtIndex directly, my object is working correctly. I get null when the index does not exist. But when I use the for loop:

 for (Pin *pin in coll) { ... } 

the code goes through the above function perfectly and fills the state with what appears to be valid values ​​and returns the number of objects, then I get the EXC_BAD_ACCESS error in the for statement itself.

What am I doing wrong in this implementation?

+4
source share
3 answers

I had similar problems, and, looking in more detail at Apple FastEnumerationSample , this part (which I missed) jumped on me:

 // We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values, // since these values are not otherwise used by the protocol. // If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated. // state->mutationsPtr MUST NOT be NULL. state->mutationsPtr = &state->extra[0]; 

The important part: state->mutationsPtr SHOULD NOT be NULL. I just used the provided sample string and it worked like a charm!

+2
source

I assume you are using ARC. The problem may be that buffer is an array of __unsafe_unretained objects, so ARC can re-issue them. But what does your objectAtIndex: method look like? This should not be a problem if you return objects that are guaranteed to live, at least as long as your object itself.

+1
source

Instead:

 id obj = [self objectAtIndex:state->state]; 

use

 __unsafe_unretained id = [self objectAtIndex:state->state]; 
0
source

All Articles