Take the 2-minute tour ×

It seems from experimentation that the collection expression is evaluated only once. Consider this example:

static NSArray *a;

- (NSArray *)fcn
    if (a == nil)
    return a;


for (NSString *s in [self fcn])
    NSLog(@"%@", s);

The output is:

2010-10-07 07:37:31.419 WidePhotoViewer Lite[23694:207] called
2010-10-07 07:37:31.420 WidePhotoViewer Lite[23694:207] one
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] two

indicating that [self fcn] is called only once.

Can anyone confirm that this is the specified (as opposed to merely observed) behavior?

What I have in mind is doing something like this:

for (UIView *v in [innerView subviews]) {

instead of this:

NSArray *vs = [innerView subviews];
for (UIView *v in vs) {


share|improve this question
Thanks to those, esp. Shmurk, who tried to answer... this indeed shed some light on the matter. (Checking an implementation to clarify a specification is hazardous. Anyway, I had already done that in preparing the question.) –  Marc Rochkind Oct 8 '10 at 2:15
add comment

4 Answers

up vote 9 down vote accepted

This kind of for loop is called a "fast enumeration" (look at the NSFastEnumeration object). Apple's documentation says that in "for obj in expression", expression yields an object that conforms to the NSFastEnumeration protocol, so I guess that's the correct behaviour: the function is called once, an iterator is created once and used in the loop.

share|improve this answer
add comment

In practice, collection is only evaluated once, you can check the source of clang, for example. When the documentation doesn't say things precise enough, you need to trust the implementation.

Yes I think Apple should clarify documentation. Please file a bug, Marc!

One pedantic way to get this is to read the margin of the official documentation, which can be found here. It's stated that

the enumerator has a mutation guard so that if you attempt to modify the collection during enumeration, an exception is raised. Since mutation of the object during iteration is forbidden, you can perform multiple enumerations concurrently.

so, the collection over which you iterate can't change anyway. It doesn't say whether it evaluates collection in

for(id obj in collection) { ... } 

once or twice, the resulting object can't change.

share|improve this answer
+1 just for suggesting a bug-filing! –  Wevah Oct 7 '10 at 16:54
add comment

Common sense dictates it to be that way. But since it is not directly stated in the Fast Enumeration Documentation, why don't you have a look at the protocol itself:


This protocol is not providing methods like nextObject, or objectAtIndex, or something like that, but instead requests a C array of objects, over which is then iterated.

Although there are strong indications, no document guarantees you that the expression is only evaluated once.

share|improve this answer
add comment

This is part of the behavior of fast enumeration. For some in-depth knowledge of the implementation of fast enumeration check out this blog post on NSBlog: Implementing Fast Enumeration.

share|improve this answer
add comment

Your Answer


