Objective-C 2.0 provides a language feature that allows you to efficiently and safely enumerate over the contents of a collection using a concise syntax.
The for…in Feature
Adopting Fast Enumeration
Using Fast Enumeration
Objective-C 2.0 provides a language feature that allows you to enumerate over the contents of a collection. The syntax is defined as follows:
for ( Type newVariable in expression ) { statements } |
or
Type existingItem; |
for ( existingItem in expression ) { statements } |
In both cases, expression yields an object that conforms to the NSFastEnumeration
protocol (see “Adopting Fast Enumeration”). The iterating variable is set to each item in the returned object in turn, and the code defined by statements
is executed. The iterating variable is set to nil
when the loop ends by exhausting the source pool of objects. If the loop is terminated early, the iterating variable is left pointing to the last iteration item.
There are several advantages to using fast enumeration:
The enumeration is considerably more efficient than, for example, using NSEnumerator
directly.
The syntax is concise.
Enumeration is “safe”—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.
Any class whose instances provide access to a collection of other objects can adopt the NSFastEnumeration
protocol. The Cocoa collection classes—NSArray
, NSDictionary
, and NSSet
—adopt this protocol, as does NSEnumerator
. It should be obvious that in the cases of NSArray
and NSSet
the enumeration is over their contents. For other classes, the corresponding documentation should make clear what property is iterated over—for example, NSDictionary
and the Core Data class NSManagedObjectModel
provide support for fast enumeration; NSDictionary
enumerates its keys, and NSManagedObjectModel
enumerates its entities.
The following code example illustrates using fast enumeration with NSArray
and NSDictionary
objects.
NSArray *array = [NSArray arrayWithObjects: |
@"One", @"Two", @"Three", @"Four", nil]; |
for (NSString *element in array) { |
NSLog(@"element: %@", element); |
} |
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: |
@"quattuor", @"four", @"quinque", @"five", @"sex", @"six", nil]; |
NSString *key; |
for (key in dictionary) { |
NSLog(@"English: %@, Latin: %@", key, [dictionary valueForKey:key]); |
} |
You can also use NSEnumerator
objects with fast enumeration, as illustrated in the following example:
NSArray *array = [NSArray arrayWithObjects: |
@"One", @"Two", @"Three", @"Four", nil]; |
NSEnumerator *enumerator = [array reverseObjectEnumerator]; |
for (NSString *element in enumerator) { |
if ([element isEqualToString:@"Three"]) { |
break; |
} |
} |
NSString *next = [enumerator nextObject]; |
// next = "Two" |
For collections or enumerators that have a well-defined order—such as NSArray
or NSEnumerator
instance derived from an array—the enumeration proceeds in that order, so simply counting iterations will give you the proper index into the collection if you need it.
NSArray *array = /* assume this exists */; |
NSUInteger index = 0; |
for (id element in array) { |
NSLog(@"Element at index %u is: %@", index, element); |
index++; |
} |
In other respects, the feature behaves like a standard for
loop. You can use break
to interrupt the iteration; and if you want to skip elements you can use a nested conditional statement as shown in the following example:
NSArray *array = /* assume this exists */; |
for (id element in array) { |
if (/* some test for element */) { |
// statements that apply only to elements passing test |
} |
} |
If you want to skip the first element then process no more than five further elements, you could do so as shown in this example:
NSArray *array = /* assume this exists */; |
NSUInteger index = 0; |
for (id element in array) { |
if (index != 0) { |
NSLog(@"Element at index %u is: %@", index, element); |
} |
if (++index >= 6) { |
break; |
} |
} |
© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-05-06)