As with Objective-C, Swift has two flavors of loops—for and while—each of which has its own two varieties. The for statement supports the traditional C-style for statement with initializer, conditional, and increment expressions, and the more modern for-in style that works with collections and other iterable constructs. The while statement supports condition-block execution, and the do-while supports block-condition execution.
for and for-in
The traditional for loop works exactly as you would expect. The general format is still for initializer; conditional; increment with the only differences being in how the initializer and conditional are expressed:
- You must define variables using the var keyword; you can’t subsequently increment a constant.
- You can rely on type inference to set the correct type for newly defined variables.
- You must use a conditional that conforms to the BooleanType protocol.
The for-in-style of loop has seen more in the way of changes with Swift. for-in was introduced with fast enumeration in Objective-C and is available to any classes that implement the NSFastEnumeration protocol. Objective-C developers most frequently use for-in loops with NSArray, NSSet, and NSDictionary collections, though any NSEnumerator-based class will also conform to NSFastEnumeration.
In Swift, the counterpart to the NSFastEnumeration protocol is SequenceType, and so anything that conforms to SequenceType is iterable. As you would expect, the default collections (array and dictionary) do so, but a few other types also implement the protocol:
- Foundation collection types—Apple has performed the requisite magic to allow the collection types you know and love to behave as iterable collections in Swift.
- Strings—A string is, after all, a collection of characters, and so the Swift String type supports iterating over the characters in a string.
- Half-open and closed ranges—Both types of ranges appear to the for-in loop as a collection of integers allowing it to iterate over the items in the collection.
- strides—The Swift stride function can be used to produce more complex ranges, including configurable increments and descending ranges.
Being able to use ranges with a for-in loop means fewer reasons than ever before to use the traditional for loop. Where you once used the following to perform a block of actions 10 times:
you can now use a range with the for-in variant instead:
Note how this improves readability; there is less chance of off-by-one errors, and if you’re the type of developer who sweats the naming of your variables, you can even use a wildcard expression to show that you don’t care what the variable is:
If you want to make your own object types iterable, you need to implement the SequenceType protocol. We will look at protocols in more detail in Chapter 13.
while and do-while
There is not much difference between while and do-while loops in Objective-C and Swift. Aside from the general changes described earlier (regarding conditions, parentheses, and braces), the only other difference you are likely to encounter is in the use of optional binding, which can be used as an alternative to using a != nil test in a conditional expression.
For example, say you wanted to travel up a UIView hierarchy to determine the topmost view—indicated by the superview property being nil. In Objective-C, you would do the following:
Using optional binding in Swift, you can instead use this code:
Don’t worry if the excessive question marks seem a bit strange—we introduce optionals and optional binding in Chapter 5.