Getting Your Feet Wet - Learning Swift Programming (2015)

Learning Swift Programming (2015)

1. Getting Your Feet Wet

Swift was released in 2014, but its development started four years earlier. Chris Lattner, the original author of the LLVM compiler and the director of Apple’s Developer Tools Department, has worked for Apple since 2005. He had to develop Swift in secret for several years and was, amazingly, able to keep it under wraps until its release in June 2014.

This chapter covers the basic building blocks of Swift. It starts with variables and constants, which allow you to reference a storage location by name. With this knowledge, you will be able to store stuff in memory. Swift has a special feature called optionals, which allow you to check for the presence of a value (by determining whether the variable or constant is nil). Swift has strong type inference; this allows you to have strict typing without needing to declare a type. This chapter reviews how Swift handles loops and if/else statements.

Building Blocks of Swift

Swift allows you to use variables and constants by associating a name with a value of some type. For example, if you want to store the string "Hi" in a variable named greeting, you can use a variable or a constant. You create a variable by using the var keyword. This establishes an associated value that can be changed during the execution of the program. If you do not want that value to be changed, you can use a constant. For example, you might record the number of login retries a user is allowed to have before being refused access to the site. In such a case, you would want to use a constant, as shown in this example:

let numberOfRetries = 5
var currentRetries = 0

Notice that you don’t use a semicolon as you would in many other languages. You do not need to use semicolons to denote the end of a statement unless you want to combine many statements together. Swift is very different from JavaScript, where omitting semicolons is generally considered unsafe. This example shows you when you would use the semicolon in Swift as multiple lines are combined into one:

let numberOfRetries = 5; var currentRetries = 0

Also unique to Swift, you can use almost any Unicode character to name your variables and constants. Developers can name resources using Hebrew, Simplified Chinese, and even special Unicode characters, such as full-color koala emoji (which is a unique Apple invention).

Using Comments

You indicate comments in Swift by using a double forward slash, exactly as in Objective-C. Here’s an example:

// This is a comment about the number of retries
let numberOfRetries = 5 // We can also put a comment on the end of a line.
/* Comments can span
multiple lines */

Inference Everywhere!

Swift uses inference to figure out what types you are attempting to use. Because of this, you do not need to declare a type when creating variables and constants. However, if you want to declare a type you may do so, and in certain situations, it is absolutely necessary. When declaring a variable, the rule of thumb is that Swift needs to know what type it is. If Swift cannot figure out the type, you need to be more explicit. The following is a valid statement:

var currentRetries = 0

Notice that Swift has to figure out what type of number this is. currentRetries may be one of the many types of numbers that Swift offers (Swift will infer this as an Int in case you are wondering, but more on that later). You could also use this:

var currentRetries:Int = 0

In this case, you explicitly set the type to Int by using the colon after the variable name to declare a type. While this is legit, it is unnecessary because Swift already knows that 0 is an Int. Swift will infer a type with initial values.

You need to declare the type if you do not know what the initial value of currentRetries will be. For example:

var currentRetries:Int

In this case, you must declare Int because without it, Swift cannot tell what type this variable will be. This is called type safety. If Swift expects a string, you must pass it a string. You cannot pass an Int when a String is expected. This is a great time saver because it means you do a lot less typing (with your fingers). Swift does a lot of the typing (inference) for you. Thanks, Swift! Swift is completely compatible with Objective-C and is able to use almost all of the APIs available to Objective-C and C (if not you can make your own bridge to make the API available). Swift also has its own types separate from Objective-C and C. For number types, Swift gives us the following:

■ Int provides 8-, 16-, 32-, and 64-bit flavors, but you will most likely stay with just Int. It’s probably large enough for your needs. Here’s what you need to know about Int:

Int on 32-bit platforms is Int32.

Int on 64-bit platforms is Int64.

That is, when you declare a variable as Int, Swift will do the work of changing that to Int32 or Int64. You don’t need to do anything on your end.

Int can be both positive and negative in value.

Int will be chosen when you declare a variable with an integer:

var someInt = 3 // this will be an Int

UInt is provided as an unsigned integer. An unsigned number must be greater than or equal to zero, whereas a signed number can be negative. For consistency, Apple recommends that you generally use Int even when you know a value will never be negative.

■ Double denotes 64-bit floating-point numbers. Double has a higher precision than float, with at least 15 decimal digits. Double will be chosen when you declare a variable with a floating-point number:

var someDouble = 3.14 // this will be a double

Combining any integer with any floating-point number results in a Double:

3 + 3.14 // 6.14 Works and will be a double
var three = 3
var threePointOne = 3.1
three + threePointOne //Error because you can't mix types

■ Float denotes 32-bit floating-point numbers. Float can have a precision as small as 6. Whether you choose Float or Double is completely up to you and your situation. Swift will choose Double when no type is declared.

Along with Decimal numbers, you can use Binary, Octal, and Hexadecimal numbers:

■ Decimal is the default for all numbers, so no prefix is needed.

■ Binary takes a 0b prefix.

■ Octal takes a 0o prefix.

■ Hexadecimal takes a 0x prefix.

You can check the type of the object like this:

var pi:Any?
pi = 3.141
pi is Double //true
pi is Float //false

You can test the class or type of an object (introspect) in this way. Notice how you declare this type as Any? in the preceding example. (You will learn more about Any in more detail later.) The question mark means that you want an optional (and you’ll learn more about this shortly as well). The Any type can be any type (exactly what it says). Because Objective-C is not as strict as Swift, and you need to be able to intermingle the two languages, Any and AnyObject were created. You’ll learn more about this later in the chapter.

Swift is one of the few programming languages that let you put underscores in numbers to make them more legible. Xcode ignores the underscores when it evaluates your code. You might find using underscores especially useful with big numbers, where you want to denote the thousand-comma separator, as in this case:

var twoMil = 2_000_000

Before you can add two numbers together, they must be of the same type. For example, the following will not work:

var someNumA:UInt8 = 8
var someNumB:Int8 = 9
someNumA + someNumB
//Int8 is not convertible to UInt8

In order to make this work, you must convert one of the types to the other by using the initializer. For example, you can use the initializer UInt8, which can convert for you:

someNumA + UInt8(someNumB)

Swift is strict in requiring you to convert types before you can combine them.

Optionals: A Gift to Unwrap

Optionals are a unique feature of Swift, and they are used absolutely everywhere. Optionals take a little getting used to but in the end they are a clever feature that helps you achieve clean-looking code with fewer lines while also being stricter.

In many languages, you need to check objects to see whether they are nil or null. Usually, you write some pseudo-code that looks like the following. In this example we check for not null in Javascript:

if(something != null) {...

Not having to write that ugly code all over the place saves you time. In Swift, an optional value contains either a value or nil to indicate that the value is missing. To mark something as optional, you just include a ? next to the type of the object. For example, here’s how you create a String optional:

var someString:String? = "Hey there!"

You can now say that someString is of type String? (which you verbalize as “String optional”) and not just of type String. Try printing that variable as an optional string and then as a regular string. Notice the difference in their returned values.

What makes optionals unique is that they must be “unwrapped” in order to get their value back. There are a couple ways to get the value out of an optional. When you see a variable of type String?, you can say that this variable may or may not contain a value. You can say, “I will test this String optional to find out if it does in fact have a value.” How do you test an optional? You use value binding.

Value binding allows you to do two things at once. First, it allows you to test the optional to see whether it is nil. Second, if that variable is not nil, value binding allows you to grab the value out of the optional and have it passed into a constant as a locally scoped variable. To see this in action, you’ll look at an example, but before you can try it out, you first need to open a new playground:

1. Open Xcode 6.

2. Click Get started with a playground.

3. Save a new playground file by giving it a filename.

Now you can try out value binding with optionals:

var hasSomething:String? = "Hey there!"
if let message = hasSomething {
"Message was legit: \(message)"
} else {
"There was no message!"
}

A couple of fancy new things are going on here. This short little blurb of code is one of the things that make Swift so fantastic. Let’s go through it one step at a time:

1. On the first line, you create a variable as usual, but you add the ? to say that this is a String optional. This means that this String may contain a value or nil. In this case, it contains a value.

2. Next, you write a conditional statement. You are testing whether the variable hasSomething is nil or not. At the same time, you are assigning that value of the optional to a constant message. If the variable contains a value, then you get a new constant (only available in the local scope, so we call it a locally scope constant), which is populated with the raw value of the optional. You will then enter into the if statement body.

3. If you do enter into that if statement, you now have a locally scoped constant message to use. This constant will not be available anywhere else in the code. You can then print a string, which contains the locally scoped constant. Swift has a special syntax for including variables in strings without having to concatenate strings in the old-school way. You can write \() and include the variable inside those parentheses. Doing this prints the variable’s contents in the middle of the string. In other languages, you might have to do something like this. Here is an example of what you might do in JavaScript on the first line and then in Objective-C on the second line:

"Message was legit" + message;
[NSString stringWithFormat:@"Message was legit: %@", message];

However, sometimes, you are absolutely sure that your optional contains a value. Swift uses optionals here. (We will get into arrays and dictionaries in Chapter 2, but think about it: If you try to grab an item from a dictionary, that item may or may not exist.) You can think of optionals as a gift that needs to be unwrapped. Now if this optional is nil inside, it will not throw an error when you try to access it, because you haven’t unwrapped it. In most languages, trying to access something of nil value throws an error. In the case of the dictionary, sometimes you are sure that the dictionary item has a value. You want to implicitly unwrap the optional.

You can force the unwrapping of an optional to get that value out by using an exclamation point. Let’s look again at our earlier example. If you were sure that the string contained a value, you could force an unwrapping of the optional like this (try it out in a playground):

var hasSomething:String? = "Hey there!" //declare the optional string
hasSomething // prints {Some "Hey there!"}
//Now force the optional to unwrap with !
hasSomething! // prints "Hey there!"

Now you can get the value out of the optional with one extra character. Remember how we said these optionals are like presents? Well, it’s sometimes good to think of them more like bombs in Minesweeper. If you are too young for Minesweeper, then think of them as presents that could contain bombs. You want to force the unwrapping of an optional only if you are sure its value is not nil. If you force the unwrapping of an optional that does contain nil, then you will throw a fatal error, and your program will crash:

var hasSomething:String? //declare the optional string with no initial
value
// Now try and force it open
hasSomething! // fatal error: unexpectedly found nil while unwrapping an Optional
value your program will crash and probably won't be accepted to the app store.

You want to get the output of the code so open up the console of the playground so you can see your output. Click the little circle in the output area or by pressing Command+Alt+Enter.

Printing Your Results

When you use the playground to test your code, you have two options for printing data. You can simply just write it, like this:

var someString = "hi there"
someString //prints "hi there" in the output area

You can also use println(), which prints to the console output area. When you are making a full-fledged app, compiling code outside a playground, you’ll want to use println(), like this, because just writing the variable will not do anything:

var someString = "hi there"
println(someString) //prints "hi there" in the console output

Implicitly Unwrapped Optionals

Sometimes you want to create an optional that gets unwrapped automatically. To do this, you assign the type with an exclamation point instead of a question mark:

var hasSomething:String! = "Hey there"// implicitly unwrapped optional string
hasSomething // print the implicitly unwrapped optional and get the
unwrapped value.

You can think of implicitly unwrapped optionals as a present that unwraps itself. You should not use an implicitly unwrapped optional if a chance exists that it may contain nil at any point. You can still use implicitly unwrapped optionals in value binding to check their values.

So why should you create implicitly unwrapped optionals in the first place if they can be automatically unwrapped? How does that make them any better than regular variables? Why even use them in the first place? These are fantastic questions, and we will answer them later, after we talk about classes and structures in Chapter 4. One quick answer is that sometimes we want to say that something has no value initially but we promise that it will have a value later. Properties of classes must be given a value by the time initialization is complete. We can declare a property with the exclamation point to say “Right now it does not have a value, but we promise we will give this property a value at some point.”

Tuples

Using tuples (pronounced “TWO-pulls” or “TUH-pulls”) is a way to group multiple values into one. Think of associated values. Here is an example with URL settings:

let purchaseEndpoint = ("buy","POST","/buy/")

This tuple has a String, a String, and a String. This tuple is considered to be of type (String, String, String). You can put as many values as you want in a tuple, but you should use them for what they are meant for. You can mix types in tuples as well, like this:

let purchaseEndpoint = ("buy","POST","/buy/",true)

This tuple has a String, a String, a String, and a Bool. You are mixing types here, and this tuple is considered to be of type (String, String, String, Bool). You can access this tuple by using its indexes:

purchaseEndpoint.1 // "POST"
purchaseEndpoint.2 // "/buy/"

There are two problems here. You can guess what POST and /buy/ are, but what does true stand for? Also, using indexes to access the tuple is not very pretty or descriptive. You need to be able to be more expressive with the tuple.

You can take advantage of Swift’s ability to name individual elements to make your intentions clearer:

let purchaseEndpoint = (name: "buy", httpMethod: "POST",URL:
"/buy/",useAuth: true)

This tuple has String, String, String, and Bool (true or false) values. Now you can access the elements in a much prettier way:

purchaseEndpoint.httpMethod = "POST"

Now this is much better. It makes much more sense and reads more like English.

You can decompose this tuple into multiple variables at once, like so:

let (purchaseName, purchaseMethod, purchaseURL, _) = purchaseEndpoint

Here, you are able to take three variables and grab the meat out of the tuple and assign it right to those variables. You use an underscore to say that you don’t need the fourth element out of the tuple.

In Chapter 3, “Making Things Happen: Functions,” you will use tuples to give functions multiple return values. You can probably imagine how this would work. Imagine having a function that returned a tuple instead of a string. You could then return all the data at once and do something like this:

let purchaseEndpoint = getEndpoint("buy") // some function that doesn't exist yet
println("You can access the purchase url at \(purchaseEndpoint.URL) using a
\(purchaseEndpoint.httpMethod)")

Number Types and Converting Between Them

Swift is interoperable with Objective-C, so you can use C, Objective-C, and Swift types all within Swift. As discussed earlier in the chapter, when you write a variable using an integer, Swift automatically declares it with a type Int, without your having to tell Swift you want an Int. In this example, you don’t tell Swift to make this variable an Int:

let theAnswerToLifeTheUniverseAndEverything = 42

Rather, Swift infers that it is an Int. Remember that on 32-bit systems, this Int will be an Int32 and on 64-bit systems, it will be an Int64. Even though you have many different Int types available to you, unless you have a need for an Int of a specific size, you should stick with Swift’s Int. When we say Int32, what we mean is a 32-bit integer. (This is similar to C.) You can also use UInt for unsigned (non-negative) integers, but Apple recommends that you stick with Int even if you know your variable is going to be unsigned.

Again, when you write any type of floating-point number (a number with a decimal), and you don’t assign a type, Swift automatically declares it with the type Double. Swift gives you Double and Float types. The difference between them is that Double has a higher precision of around 15 decimal digits, whereas Float has around 6. You have to decide at coding time which is right for your situation. Here is an example of Swift automatically converting to a Double:

let gamma = 0.57721566490153286060651209008240243104215933593992
gamma //prints 0.577215664901533 which is 15 decimal places. Inferred to a
double

Swift is strict about its types and how you can combine them together. If something is meant to be a String, and you give it an Int, then you will get an error. Swift wants you to be explicit with types. For example, this will not work:

var someInt = 5 // Inferred to be an Int
someInt + 3.141 // throws an error

If you want to combine an Int and a Double you must first convert the Int to a Double or vice versa, depending on your preference. Here we combine an Int and Double by converting the Int to a Double:

var someInt = 5 // Inferred to be an Int
Double(someInt) + 3.141

var someInt = 5 // Inferred to be an Int
Float(someInt) + 3.141 // In this case 3.141 will be inferred to a Float so
it can combine with a Float

var someInt = 5 // Inferred to be an Int
Float(someInt) + Double(3.141) //This will throw an error and will not work

You can use the initializer of the number type to convert between types. For example, you can use Float() to convert any number type into a Float. You can see why this works if you look in the source code by holding Command and clicking the word Float. You then now see the Float source (in summary, not the real deal). If you go down to around line 2096, you see that Swift has created initializers for every other number type. It uses extensions to achieve this. You can probably guess that Swift takes the Float source and extends it with new initializers and other functionality. What is so cool about this is that you can do the same thing yourself. Apple wrote Swift with Swift.

So again, when you want to perform any operations on two or more number types, all sides of the operation must be of the same type. You’ll see this pattern often in Swift, and not just with numbers. For example, you cannot directly add a UInt8 and a UInt16 unless you first convert the UInt8 to a UInt16 or vice versa.

Coming to Swift from Objective-C and C

If you are coming from a world of Objective-C and C, then you know that you have many number types at your disposal. Number types like CGFloat and CFloat are necessary to construct certain objects. For example, SpriteKit has the SKSpriteNode as a position property, which is a CGPoint with two CGFloats.

What do you do? What is the different between CGFloat and Float? Well if you Command+click the CGFloat, you see that CGFloat is just a typealias for Double. This is what the code actually says:

typealias CGFloat = Double

What is a typealias? Great question. A typealias is just a shortcut name to an already existing type. It basically gives the type a substitute name. You could give String an alternate name type of Text, like this:

typealias Text = String
var hello:Text = "Hi there"

Now hello is of type Text, which was previously nonexistent. So if CGFloat is a typealias for a Double, this just means that when you make CGFloats, you are really just making Doubles. It’s worth it to Command+click around and see what is mapping to what. For example, a CFloat is a typealias for Float, and a CDouble is a typealias for Double.

Control Flow: Making Choices

Controlling the order in which code executes is a crucial aspect of any programming language. By building on the traditions of C and C-like languages, Swift’s control flow constructs allow for powerful functionality while still maintaining a familiar syntax.

for Loops

At its most basic, a for loop allows you to execute code repeatedly. You can also say that code statements are “looping” a certain number of times (or infinitely). In the Swift language, there are two distinct types of for loops to consider. There is the traditional for-condition-increment loop, and there is the for-in loop. for-in is often associated with a process known as fast enumeration—a simplified syntax that makes it easier to run specific code for every item in a range, sequence, collection, or progression. Using for-in also decreases the implementation overhead.

for-condition-increment Loops

You use a for-condition-increment loop to run code repeatedly until a condition is met. On each loop, you typically increment a counter until the counter reaches the desired value. You can also decrement the counter until it drops to a certain value, but that is less common. The basic syntax of this type of loop in Swift looks something like this:

for initialization; conditional expression; increment {
statement
}

As in Objective-C and C, in Swift you use semicolons to separate the different components of the for loop. However, Swift doesn’t group these components into parentheses. Aside from this slight syntactic difference, for loops in Swift function as they would in any C language.

Here’s a simple example of a for-condition-increment loop that simply prints Hello a few times.

for var i = 0; i < 5; ++i {
println("Hello there number \(i)")
}
// Hello there number 0
// Hello there number 1
// Hello there number 2
// Hello there number 3
// Hello there number 4

This is fairly straightforward, but notice the following:

■ Variables or constants declared in the initialization expression are valid only within the scope of the loop itself. If you need to access these values outside the scope of the for loop, then the variable must be declared prior to entering the loop, like this:

var i = 0
for i; i < 5; ++i {...

■ If you’re coming from another language, particularly Objective-C, you will notice that the preceding example uses ++i instead of i++. Using ++i increments i before returning its value, while i++ increments i after returning its value. Although this won’t make much of a difference in the earlier example, Apple specifically suggests that you use the ++i implementation unless the behavior of i++ is explicitly necessary.

■ To avoid an infinite loop, it is necessary to create a for loop where the conditional expression will eventually evaluate to false. The earlier example increments i after each time the bracketed statements execute, and the conditional expression (i < 5) will be false when i is 5 or greater; at that point, the loop exits. Writing true in there would make it loop forever.

for-in Loops

In addition to giving you the traditional for-condition-increment loop, Swift builds on the enumeration concepts of Objective-C and provides an extremely powerful for-in statement. Its syntax makes some of the most common use cases extremely concise and easy.

With for-in, you can iterate numbers in a range. For example, you could use a for-in loop to calculate values over time. Here you can loop through 1 to 4 with less typing:

class Tire { }
var tires = [Tire]()
for i in 1...4 {
tires.append(Tire())
}
println("We have \(tires.count))

You can ignore the class and array syntax here since we haven’t covered it yet. This example uses a ... range operator for an inclusive range. This means that the range begins at the first number and includes all the numbers up to and including the second number. If you wanted to go up to the second number but not include it, you would use the ..< range operator. The previous example, rewritten to use the non-inclusive range operator, would look like this:

class Tire { }
var tires = [Tire]()
// 1,2,3 but not 4
for i in 1..<4 {
tires.append(Tire())
}
println("We have \(tires.count))

As you can see, the results are almost identical, and whichever form you choose is largely a matter of what you need. Both examples provide concise and readable code. In situations where you don’t need access to i, you can disregard the variable altogether by replacing it with an underscore (_). The code now might look something like this:

class Tire { }
var tires = [Tire]()
// 1,2,3, and including 4
for _ in 1...4 {
tires.append(Tire())
}
println("We have \(tires.count))

Another extremely common use of for loops is to iterate through collections and perform a set of statements for each item within the collection. Let’s pretend that a bunch of tires have gone flat, and you need to refill them with air. You could use this Swift code:

class Tire {var air = 0}
for tire in tires {
tire.air = 100
}

With this type of declaration, Swift uses type inference to assume that each object in an array of type [Tire] will be a Tire. This means it is unnecessary to declare the type explicitly. In a situation where the array’s type is unknown, the implementation would look like this:

class Tire {var air = 0}
for tire: Tire in tires {
tire.air = 100
}
println("We made \(tires.count) tires")
// We made 4 tires

Swift always has to know the type.

In Swift, a String is really a collection of Character values in a specific order. You can iterate values in a String by using a for-in statement, like so:

for char in "abcdefghijklmnopqrstuvwxyz" {
println(char)
}
// a
// b
// c
// etc ...

As with any other collection, it is simple and concise to iterate through each item. There are still situations in which you need access to the index number as well as the object. One option is to iterate through a range of indexes and then get the object at the index. You would write that like this:

let array = ["zero", "one", "two", "three", "four"]
for idx in 0..<array.count {
let numberString = array[idx]
println("Number at index \(idx) is \(numberString)")
}
// Number at index 0 is zero
// Number at index 1 is one
// etc ...

This code executes fine, but Swift provides a global enumerate function that makes this type of statement a bit more concise. If you were to use the for-in statement in conjunction with the enumerate function, the preceding example would look like this:

let array = ["zero", "one", "two", "three", "four"]
for (idx, numberString) in enumerate(array) {
println("Number at index \(idx) is \(numberString)")
}
// Number at index 0 is zero
// Number at index 1 is one
// etc ...

This type of enumeration is extremely clear and concise, and you would use it when the situation requires an array element and its index. You are able to grab the index of the loop and the item being iterated over!

Up to this point, all the code in this chapter has known ahead of time how many times it should iterate. For situations in which the number of required iterations is unknown, it can be useful to use a while loop or a do whileloop. The syntax to use these while loops is very similar to that in other languages, minus the parentheses. Here’s an example:

var i = 0
while i < 10 {
i++
}

Here, you are saying that this loop should continue while the value of i is less than 10. In this situation, i starts out at 0, and on each run of the loop, i gets incremented by 1. You can have an infinite loop this way. You have to decide if you need an infinite loop. There are times when an infinite loop is necessary.

For example, in the playground, some types of code won’t respond to a URL callback because the NSRunLoop isn’t running. For instance, trying to grab some data from a URL with NSSession.sharedSession().dataTaskWithURL() does not work because the NSRunLoop is listening for things like URL callbacks. You need to do a little hack to get the run loop running: use a continuous whileloop that never ends. In this case, you’ll use while true to achieve this:

import Cocoa
import XCPlayground
while true {
NSRunLoop.currentRunLoop().runMode(
NSDefaultRunLoopMode,
beforeDate:NSDate()
)
usleep(10)
}

Now things like dataTaskWithURL will work in the playground. Notice in this example you use a while loop that always evaluates to true. Therefore, this loop will loop forever.

The following example combines all the looping capabilities and if/else statements you now know about to find the prime numbers. Here’s how you could find the 200th prime number:

import Cocoa
var primeList = [2.0]
var num = 3.0
var isPrime = 1
while countElements(primeList) < 200 {
var sqrtNum = sqrt(num)
// test by dividing only with prime numbers
for primeNumber in primeList {
// skip testing with prime numbers greater
// than square root of number
if num % primeNumber == 0 {
isPrime = 0
break
}
if primeNumber > sqrtNum {
break
}
}
if isPrime == 1 {
primeList.append(num)
} else {
isPrime = 1
}
//skip even numbers
num += 2
}
primeList[199]

Grabbing primeList[199] will grab the 200th prime number because arrays start at 0. You can combine while loops with for-in loops to calculate prime numbers. If you try this out in the playground, make sure that your while loop does not run while you are writing your code, or you might get super annoyed because the while loop will go on forever while you try to type, and this may crash your Xcode. Try setting while to false. Then change it back when you are done.

Making Choices with Conditionals (if/else)

It’s important to be able to make your code make decisions and change directions. Without this, your code would take the same path every time it is run. You make if/else choices yourself all the time. You might say to yourself, “I’ll keep pouring water in this glass if the water is below the top line of the glass.” Or you might say to yourself, “If the car in front of me slows down below 55 mph, I’ll pass him on the left. Otherwise, I’ll stay in this lane.” Your decision making is more complicated than this, though. You need to think of other factors and might say something like, “If the driver in front of me slows down below 55 mph, I’ll pass him on the left if no one in the third lane is coming and if there are no cops around.” Here’s how you might make such decision making in Swift code:

var carInFrontSpeed = 54
if carInFrontSpeed < 55 {
println("I am passing on the left")
} else {
println("I will stay in this lane")
}

Here, you use Swift’s if and else statements to make a decision based on whether a variable is less than 55. Since the integer 54 is less than the integer 55, you show the statement in the if section. One caveat to if statements is that they cannot use integers converted to true or false. For example, the following will throw an error.

if 1 { //throws an error
//Do something
}

In the highway passing example, you want to check multiple statements to see if they’re true or false. You want to check whether the car in front of you slows down below 55 mph and whether there is a car coming and whether there is a police car nearby. You can check all three in one statement with the && operator to say that the statement to the left of the && must be true as well as the statement to the right of the &&. Here’s what it looks like:

var policeNearBy = false
var carInLane3 = false
var carInFrontSpeed = 45
if !policeNearBy && !carInLane3 && carInFrontSpeed < 55 {
println("We are going to pass the car.")
} else {
println("We will stay right where we are for now.")
}

In this example, you make sure that all three situations are false before you move into the next lane. You can also check to see if any of the statements are true by using the or operator, which is written as two pipes: ||. You could rewrite the preceding statement by using the or operator. This example just checks for the opposite of what the last example checks for:

var policeNearBy = false
var carInLane3 = false
var carInFrontSpeed = 45
if policeNearBy || carInLane3 || carInFrontSpeed > 55 {
println("We will stay right where we are for now.")
} else {
println("We are going to pass the car.")
}

If any of the preceding variables are true, then you will stay where you are: You will not pass the car.

Sometimes you need to check for other conditions. You might want to check whether one condition is not met instead of just going straight to an else. You can use else if for this purpose, as shown in this example:

var policeNearBy = false
var carInLane3 = false
var carInFrontSpeed = 45
var backSeatDriverIsComplaining = true
if policeNearBy || carInLane3 || carInFrontSpeed > 55 {
println("We will stay right where we are for now.")
} else if backSeatDriverIsComplaining {
println("We will try to pass in a few minutes")
}else {
println("We are going to pass the car.")
}

You can group as many of these else ifs together as you need. However, when you start grouping a bunch of else if statements together, it might be time to use the switch statement.

Switching It Up: switch Statements

You get much more control if you use a switch statement to control your flow instead of using tons of if else statements. Swift’s switch statements are very similar to those in other languages with some extra power added in. One little caveat is that in Swift, you do not have to use break to stop a condition from running through each case statement. Swift automatically breaks on its own when the condition is met.

Another caveat about switch statements is that they must be exhaustive. That is, if you are using a switch statement on an int, then you need to provide a case for every int ever. Because this is not possible, you can use the default statement to provide a match when nothing else matches. Here is a basic switch statement:

var num = 5
switch num {
case 2:println("It's two")
case 3:println("It's three")
default:println("It's something else")
}

Notice that you must add a default statement. As mentioned earlier, if you try removing it, you will get an error because the switch statement must exhaust every possibility. Also note that case 3 will not run if case 2 is matched because Swift automatically breaks for you.

You can also check multiple values at once. This is similar to using the or operator (||) in if else statements. Here’s how you do it:

var num = 5
switch num {
case 2,3,4:println("It's two") // is it 2 or 3 or 4?
case 5,6:println("it's five") // is it 5 or 6?
default:println("It's something else")
}

In addition, you can check ranges. The following example determines whether a number is something between 2 and 6:

var num = 5
switch num {
// including 2,3,4,5,6
case 2...6:println("num is between 2 to 6")
default:println("None of the above")
}

You can use tuples in switch statements. You can use the underscore character (_) to tell Swift to “match everything.” You can also check for ranges in tuples. Here’s how you could match a geographic location:

var geo = (2,4)
switch geo {
//(anything, 5)
case (_,5):println("It's (Something,5)")
case (5,_):println("It's (5,Something)")
case (1...3,_):println("It's (1 2 or 3, Something)")
case (1...3,3...6):println("This would have matched but Swift already found
a match")
default:println("It's something else")
}

In the first case, you are first trying to find a tuple whose first number is anything and whose second number is 5.

In the second case, you are looking for the opposite of the first case.

In the third case, you are looking for any number in the range 1 to 3, including 3, and the second number can be anything. Matching this case causes the switch to exit.

The next case would also match, but Swift has already found a match, so it never executes.

If you want the typical Objective-C functionality, where the third case and fourth case match, you can add the keyword fallthrough to the case, and the case will not break:

var geo = (2,4)
switch geo {
//(anything, 5)
case (_,5):println("It's (Something,5)")
case (5,_):println("It's (5,Something)")
case (1...3,_):
println("It's (1 2 or 3, Something)")
fallthrough
case (1...3,3...6):
println("We will match here too!")
default:println("It's something else")
}

Now the third case and fourth case match, and you get both println statements:

It's (1, 2 or 3, Something)
We will match here too!

Remember the value binding example from earlier? You can use this same idea in switch statements. Sometimes it’s necessary to grab values from the tuple. You can even add in a where statement to make sure you get exactly what you want:

var geo = (2,4)
switch geo {
case (_,5):println("It's (Something,5)")
case (5,_):println("It's (5,Something)")
case (1...3,let x):
println("It's (1 2 or 3, \(x))")
case let (x,y):
println("No match here for \(x) \(y)")
case let (x,y) where y == 4:
println("Not gonna make it down here either for \(x) \(y)")
default:println("It's something else")
}

This is the mother of all switch statements. Notice that the last two cases will never run. You can comment out the third then fourth switch statement to see each run. We talked about the first case and second case. The third case sets the variable x (to 4) to be passed into the println if there is a match. The only problem is that this works like the underscore by accepting everything. You can solve this with the where keyword. In the fourth case, you can declare both x and y at the same time by placing the let outside the tuple. Finally, in the last case, you want to make sure that you pass the variables into the statement, and you want y to be equal to 4. You control this with the where keyword.

Stop...Hammer Time

It’s important to have some control over your switch statements and loops. You can use break, continue, and labels to control them.

Using break

Using break stops any kind of loop (for, for in, or while) from carrying on. Say that you’ve found what you were looking for, and you no longer need to waste time or resources looping through whatever items remain. Here’s what you can do:

var mystery = 5
for i in 1...8 {
if i == mystery {
break
}
println(i) // Will be 1, 2, 3, 4
}

The loop will never print 5 and will never loop through 6, 7, or 8.

Using continue

Much like break, continue will skip to the next loop and not execute any code below the continue. If you start with the previous example and switch out break with continue, you will get a result of 1, 2, 3, 4, 6, 7, and 8:

var mystery = 5
for i in 1...8 {
if i == mystery {
continue
}
println(i) // Will be 1, 2, 3, 4, 6, 7, 8
}

Using Labeled Statements

break and continue are fantastic for controlling flow, but what if you had a switch statement inside a for in loop? You want to break the for loop from inside the switch statement, but you can’t because the breakyou write applies to the switch statement and not the loop. In this case, you can label the for loop so you can say that you want to break the for loop and not the switch statement:

var mystery = 5
rangeLoop: for i in 1...8 {
switch i {
case mystery:
println("The mystery number was \(i)")
break rangeLoop
case 3:
println("Was three. You have not hit the mystery number yet.")
default:
println("was some other number \(i)")
}
}

Here, you can refer to the right loop or switch to break. You could also break for loops within for loops without returning a whole function. The possibilities are endless.

Summary

This chapter has covered a lot of ground. You can see that Swift isn’t another version of Objective-C. Swift is a mixture of principles from a lot of languages, and it really is the best of many languages. It has ranges, which pull syntax straight out of Ruby. It has for in loops with enumerate and tuples, which both are straight out of Python. It has regular for loops with i++ or ++i, which come from C and many other languages. It also has optionals, which are Swift’s own invention.

You’ll see shortly that Swift has a lot of cool features that make it easy to use along with your Objective-C and C code. You have already gotten a small taste of arrays. Chapter 2, “Collecting Data,” covers arrays and dictionaries in detail. You’ll see how Swift’s strong typing and optionals come into play.