A type that supplies the values of a sequence one at a time.
- Xcode 8.0+
Iterator protocol is tightly linked with the
Sequence protocol. Sequences provide access to their elements by creating an iterator, which keeps track of its iteration process and returns one element at a time as it advances through the sequence.
Whenever you use a
in loop with an array, set, or any other collection or sequence, you’re using that type’s iterator. Swift uses a sequence’s or collection’s iterator internally to enable the
in loop language construct.
Using a sequence’s iterator directly gives you access to the same elements in the same order as iterating over that sequence using a
in loop. For example, you might typically use a
in loop to print each of the elements in an array.
Behind the scenes, Swift uses the
animals array’s iterator to loop over the contents of the array.
The call to
animals returns an instance of the array’s iterator. Next, the
while loop calls the iterator’s
next() method repeatedly, binding each element that is returned to
animal and exiting when the
next() method returns
Using Iterators Directly
You rarely need to use iterators directly, because a
in loop is the more idiomatic approach to traversing a sequence in Swift. Some algorithms, however, may call for direct iterator use.
One example is the
reduce1(_:) method. Similar to the
reduce(_: method defined in the standard library, which takes an initial value and a combining closure,
reduce1(_:) uses the first element of the sequence as the initial value.
Here’s an implementation of the
reduce1(_:) method. The sequence’s iterator is used directly to retrieve the initial value before looping over the rest of the sequence.
reduce1(_:) method makes certain kinds of sequence operations simpler. Here’s how to find the longest string in a sequence, using the
animals array introduced earlier as an example:
Using Multiple Iterators
Whenever you use multiple iterators (or
in loops) over a single sequence, be sure you know that the specific sequence supports repeated iteration, either because you know its concrete type or because the sequence is also constrained to the
Obtain each separate iterator from separate calls to the sequence’s
make method rather than by copying. Copying an iterator is safe, but advancing one copy of an iterator by calling its
next() method may invalidate other copies of that iterator.
in loops are safe in this regard.
Adding IteratorProtocol Conformance to Your Type
Implementing an iterator that conforms to
Iterator is simple. Declare a
next() method that advances one step in the related sequence and returns the current element. When the sequence has been exhausted, the
next() method returns
For example, consider a custom
Countdown sequence. You can initialize the
Countdown sequence with a starting integer and then iterate over the count down to zero. The
Countdown structure’s definition is short: It contains only the starting count and the
make method required by the
make method returns another custom type, an iterator named
Countdown type keeps track of both the
Countdown sequence that it’s iterating and the number of times it has returned a value.
Each time the
next() method is called on a
Countdown instance, it calculates the new next value, checks to see whether it has reached zero, and then returns either the number, or
nil if the iterator is finished returning elements of the sequence.
Creating and iterating over a
Countdown sequence uses a
Countdown to handle the iteration.