I have a class and I want my class to confirm to the NSFastEnumeration Protocol. I've read the documentation but it's not really clear. Can someone please tell me what the protocol method should return and how it works?
-
possible duplicate of [Proper construction of NSFastEnumeration class](http://stackoverflow.com/questions/3468349/proper-construction-of-nsfastenumeration-class) – outis Jul 20 '12 at 05:35
2 Answers
Apple's FastEnumerationSample shows you what to do, but here's a breakdown.
The sole NSFastEnumeration
method, countByEnumeratingWithState:objects:count:
, returns chunks of the collection. It's executed whenever more items are needed, until it indicates that there are no more items by returning 0. A chunk is passed as a C array of id
s.
Within the method, the state
parameter holds most (if not all) of the data you'll be using. You'll need to set state->itemsPtr
and update state->state
with each separate invocation of countByEnumeratingWithState:objects:count:
. Here's a brief description of each field of NSFastEnumerationState
:
state
: represents the position in the sequence being iterated over. For indexed collections, this would be the index. For linked lists, this could be a node pointer. For other types, this could be a more complex type (e.g. for a tree,state->state
could be an NSMutableArray used as a stack to store nodes). WhencountByEnumeratingWithState:objects:count:
is first called,state->state
is 0; check for this condition to initialize thestate
struct.itemsPtr
: the items in the chunk; points to a C array ofid
s. Cocoa will loop over this array, binding each item in turn to the variable named in the for-in loop.mutationsPtr
: for mutable collections, used to indicate that the collection has changed since the last call tocountByEnumeratingWithState:objects:count:
. Typically, you'd set this once when initializing the state. Collection mutators increment the value that this points to. Cocoa will compare the value returned bycountByEnumeratingWithState:objects:count:
to the value from the previous invocation; if they're different, Cocoa will throw an exception.extra
: you can use this to store extra data.
You can set state->state
and any element of state->extra
to whatever you wish; they're provided solely for your convenience, and do not affect Cocoa. state->itemsPtr
, *state->mutationsPtr
and the value returned by the method, however, do affect Cocoa.
As for the two other method parameters, stackbuf
is an array that Cocoa provides to hold items. Its use is optional, but if you don't use it, you'll have to allocate storage space for state->itemPtr
. If you use it, set state->itemsPtr
to stackbuf
with each invocation. len
is the length of stackbuf
, the maximum number of items that you'll be able to store in it.
Further reading:
-
would the down-voter care to explain why referencing sample code which contains a documented implementation is worthy of a down-vote? the OP never mentioned reading the sample. the author of the sample code put more time into the example than the typical SO answer. taaaaanks – justin Feb 02 '11 at 10:11
-
two wrongs don't make a right… ( i.e. a bad answer... for a bad question). i'm not voting you up or down, as this type of answer is annoyingly pervasive.. IMO, it should be assumed that OP's have read the official documentation, always, and either there is something "beyond" what is stated in the "official docs" - that can be elaborated on, here… or the question should be voted down. just my $.02. – Alex Gray Jan 18 '12 at 04:18
-
@alex there's no need to assume the OP had read the docs - that's stated in the OP. the OP did not mention having seen the sample code which explains and details this subject quite well. the terseness in my answer seemed appropriate because I would have had to distill and repeat what the sample already explains. of course, these comment fields and new questions can be asked if further clarification is needed. considering the answer was marked as solved, and the number of upvotes, you might consider the answer a good enough push in the right direction for the general case. (cont) – justin Jan 18 '12 at 05:22
-
(cont) SO doesn't need to be a self-contained replacement for everything Apple's published in documentation, samples, and videos. why repeat the work unnecessarily? – justin Jan 18 '12 at 05:23
-
@Justin: not the downvoter, but I'd assume it's because [answers consisting solely of a link](http://meta.stackexchange.com/q/8231/133817) are discouraged on SO. Instead, distill the linked page down to its essentials in the answer. – outis Jul 20 '12 at 06:09
-
Second link is broken. Should be: http://www.cocoawithlove.com/2008/05/implementing-countbyenumeratingwithstat.html -- NB: the Mike Ash link is terrible, way over-complicated. The CCwL link is much, much better written! – Adam Feb 10 '14 at 14:35
Just reviving this thread after finding an excellent explanation. The Apple link seems to be broken. You can try here: https://developer.apple.com/library/ios/#samplecode/FastEnumerationSample/Introduction/Intro.html
The best example for implementing fast enumeration that I've found is at: http://mikeash.com/pyblog/friday-qa-2010-04-16-implementing-fast-enumeration.html. It looks much worse than it is.

- 150
- 7