8.9.3 Fast Enumeration Details
Here is a more technical description with the gory details. Consider the code
for (object expression in collection expression)
{
statements
}
here is what happens when you run it:
- collection expression is evaluated exactly once and the
result is used as the collection object to iterate over. This means
it is safe to write code such as
for (object in [NSDictionary
keyEnumerator]) ...
.
- the iteration is implemented by the compiler by repeatedly getting
batches of objects from the collection object using the fast
enumeration protocol (see below), then iterating over all objects in
the batch. This is faster than a normal enumeration where objects are
retrieved one by one (hence the name “fast enumeration”).
- if there are no objects in the collection, then
object expression is set to
nil
and the loop
immediately terminates.
- if there are objects in the collection, then for each object in the
collection (in the order they are returned) object expression
is set to the object, then statements are executed.
- statements can contain
break
and continue
commands, which will abort the iteration or skip to the next loop
iteration as expected.
- when the iteration ends because there are no more objects to iterate
over, object expression is set to
nil
. This allows
you to determine whether the iteration finished because a break
command was used (in which case object expression will remain
set to the last object that was iterated over) or because it iterated
over all the objects (in which case object expression will be
set to nil
).
- statements must not make any changes to the collection
object; if they do, it is a hard error and the fast enumeration
terminates by invoking
objc_enumerationMutation
, a runtime
function that normally aborts the program but which can be customized
by Foundation libraries via objc_set_mutation_handler
to do
something different, such as raising an exception.