Chapter    8

Repeating Code with Loops

The basic goal of programming is to write as little code as possible that does as much as possible. The less code you write, the easier the program will be to understand and modify later. The more your code does, the more powerful your program will be.

One way to write less code is to reuse code stored in functions. A second way to reuse code is through loops. A loop runs one or more lines of code multiple times, thereby eliminating the need to write multiple, redundant lines of code.

For example, if you wanted to print a message five times, you could write the following:

print ("Hello")
print ("Hello")
print ("Hello")
print ("Hello")
print ("Hello")

This is tedious but it will work. However, if you suddenly decide you need to print a message one thousand times, now you’d have to write that command one thousand times. Not only is typing the same command tedious, but it increases the chance of making a mistake in one of those commands.

A far simpler method is to use a loop. A loop lets you write one or more commands once and then run those commands as many times as you want such as:

var counter : Int = 1
while counter <= 5 {
    print ("Hello")
    counter++
}

The above loop runs five times and prints “Hello” five times. If we wanted to print “Hello” one thousand times, we could just replace the number 5 with the number 1000. Loops make code easier to write and modify while doing more work at the same time.

The while Loop

The simplest loop in Swift is called the while loop , which looks like this:

while BooleanValue {

}

Before the while loop does anything, it first checks if a Boolean value is true or false. If it’s true, then it runs the code inside its curly brackets once. Then it checks its Boolean value again to see if it’s changed to false or if it’s still true. The moment this Boolean value becomes false, the while loop stops.

Because the while loop checks a Boolean value before doing anything, it’s possible that the while loop may never run any of its code. More importantly, the while loop only runs if its Boolean value is true. That means somewhere inside the while loop’s curly brackets, there must be code that eventually changes this Boolean value to false.

If a while loop fails to change its Boolean value from true to false, then the loop will run forever, which is known as an endless loop. An endless loop may crash or freeze your program so it no longer responds to the user or works.

At the simplest level, a while loop’s Boolean value can just be true or false such as:

while true {

}

More commonly, while loops use comparison operators to determine a Boolean value such as:

while counter <= 5 {

}

As long as “counter <=5” remains true, the while loop will run. The moment “counter <= 5” is no longer true, the while loop will stop.

When using while loops, you need to define the Boolean value before the loop begins (to make sure it’s either true or false), and then you must change the Boolean value somewhere inside the while loop (to make sure the while loop eventually stops).

To see how Boolean values work with a while loop, create a new playground by following these steps:

  1. Start Xcode.
  2. Choose File image New image Playground. (If you see the Xcode welcome screen, you can also click on Get started with a playground.) Xcode asks for a playground name and platform.
  3. Click in the Name text field and type LoopingPlayground.
  4. Click in the Platform pop-up menu and choose OS X. Xcode asks where you want to save your playground file.
  5. Click on a folder where you want to save your playground file and click the Create button. Xcode displays the playground file.
  6. Edit the code as follows:
    import Cocoa

    var counter = 1

    while counter <= 10 {
        print ("Hello")
        counter++
    }

Note that the “var counter : Int = 1” line defines the variable that the while loop uses to determine a Boolean value (true or false). Also note the “counter++” line inside the while loop. This constantly changes the variable used by the while loop to determine when to stop. By changing the Boolean comparison (counter <=10), you can change how many times the while loop runs as shown in Figure 8-1.

9781484212349_Fig08-01.jpg

Figure 8-1. Running a while loop in a playground

When using a while loop, keep in mind the following:

  • Before the while loop, make sure to define any variables used by the while loop’s Boolean value
  • A while loop may run zero or more times
  • Inside the while loop, make sure the Boolean value used by the while loop can change to false eventually to avoid creating an endless loop

The repeat-while Loop

As an alternative to the while loop, Swift also offers a repeat-while loop that works almost the same. The only difference is that instead of checking a Boolean value before running, the repeat-while loop checks its Boolean value after it runs.

That means the do-while loop will always run at least once. The structure of a do-while loop looks like this:

repeat {

} while BooleanValue

Like the while loop, the repeat-while loop also needs code inside its loop that can change its Boolean value from true to false, and it also needs code before the repeat-while loop to initialize any variables that are used to calculate the repeat-while loop’s Boolean value.

To see how Boolean values work with a repeat-while loop, follow these steps:

  1. Make sure the LoopingPlayground file is loaded in Xcode.
  2. Edit the code as follows:
    import Cocoa

    var counter = 1
    repeat {
        print ("Goodbye")
        counter++
    } while counter <= 10

Notice that the Boolean value (counter <= 10) determines how many times the do-while loop runs as shown in Figure 8-2. Also note that “counter++” is equivalent to “counter = counter + 1”.

9781484212349_Fig08-02.jpg

Figure 8-2. Running a repeat-while in a playground

Remember, the main difference between the while loop and the repeat-while loop is that the repeat-while loop always runs at least once while the while loop can run zero times.

The for Loop That Counts

Depending on the Boolean value, both the while and repeat-while loop can run multiple times. If your code counts like the previous while and repeat-while loop examples did, then you can specify how many times the loop repeats. However, a while or repeat-while loop could possibly run a different number of times depending in its Boolean value.

For example, a while or repeat-while loop might ask a user to type in a password. If the password is invalid, the loop will ask for a valid password again. Since you never know how many times a user might need to try until typing a correct password, you have no idea beforehand how many times a while or repeat-while loop will run.

That’s the purpose of the for loop: to run a fixed number of times. With a for loop you need to define the following:

  • A counting variable
  • The initial value of the counting variable
  • The ending value of the counting variable often defined by a comparison operator
  • The increment/decrement value for counting up or down

The structure of the for loop looks like this:

for var startingValue; BooleanValue; incrementValue {

}

The startingValue needs to define a variable name for counting and an initial value such as I = 1.

The BooleanValue needs to evaluate to a true or false value that uses the variable used for counting, often using a comparison operator.

The incrementValue defines how to count. Counting usually occurs by adding 1, but you can count by larger increments such as by 5 or 10, or even by negative numbers to count backwards. Counting typically uses the increment/decrement operators (such as i++) or the compound assignment operator (such as i += 15).

A typical for loop might look like this:

for var i = 1; i <= 10; i++ {

}

In this for loop example, the starting value defines a variable called “i” and sets its initial value to 1.

Then the Boolean value is defined by “i <= 10” that uses the counting variable “i”.

The increment value is “i++,” which simply adds 1 to the value of the “i” variable.

Now this for loop starts counting at 1, keeps repeating the loop and adding 1 to the “i” variable, and stops only when the Boolean value “i <= 10” is no longer true, which occurs when the “i” variable equals 11.

To see how Boolean values work with a for loop, follow these steps:

  1. Make sure the LoopingPlayground file is loaded in Xcode.
  2. Edit the code as follows:
    import Cocoa

    for var i = 1; i <= 10; i++ {
        print ("Greetings")
    }

    for var i = 21; i <= 120; i += 10 {
        print ("Greetings")
    }

Notice that in the second for loop, the initial starting value is not 1 and the increment counter does not add by 1. Yet it still produces the exact same result as the first for loop. You can get as creative as you want with your for loops in choosing a starting value, a Boolean value to stop the loop, and an increment counter. However, it’s best to keep for loops as simple as possible so they’ll be easy to understand and modify. Figure 8-3 shows the results of the two for loops running.

9781484212349_Fig08-03.jpg

Figure 8-3. Running two identical for loops

The for-in Statement

A for loop always runs a fixed number of times based on its starting value, its Boolean value, and its increment counter. However, you must specify the Boolean value to make the for loop eventually stop.

Since you may not always know when a for loop should stop based on different data, Swift also offers a for-in loop. The main advantage is that the for-in loop automatically knows how to count so you don’t have to specify when to stop.

The structure of a for-in loop looks like this:

for countingVariable in listOfItems {

}

The countingVariable counts each item in a list of some kind. That list can be a string or an array (which you’ll learn about later). The main idea is that a for-in loop automatically knows how to count how many items are in a list.

For example, if you wanted to run a for loop a fixed number of times based on the length of a string, you could do the following:

let name = "Oscar"
var nameLength = count(name)

for var i = 0; i < nameLength; i++ {
    print ("Hello")
}

In this example, “name” holds the five-character string “Oscar.” The “nameLength” variable counts the number of characters in the “name” variable (which is 5). Now the for loop uses the length of the “Oscar” string (5) to determine how many times to run the for loop.

Here’s how the equivalent for-in loop looks:

for name in "Oscar" {
    print ("Hello")
}

Notice how much simpler the for-in loop looks. This for-in loop keeps running based on the number of characters stored in the “Oscar” string, which is 5. Since the for-in loop can automatically count by itself, it reduces the amount of code you need to write while increasing accuracy at the same time.

The for-in loop is especially handy for working with arrays (which you’ll learn about later). To see how for-in loops can work, follow these steps:

  1. Make sure the LoopingPlayground file is loaded in Xcode.
  2. Edit the code as follows:
    import Cocoa

    let names = ["Oscar", "Sally", "Marty", "Louis"]
    for person in names {
        print (person)
    }

Figure 8-4 shows how the for-in loop runs four times because the “names” array contains four items. If you add or subtract a name from this array, the for-in loop automatically counts the new number of items in the array.

9781484212349_Fig08-04.jpg

Figure 8-4. Counting with a for-in loop

Exiting Loops Prematurely

Normally loops run until a Boolean value changes. However, you can prematurely exit out of a loop by using the break command. Normally this loop would run four times:

let names = ["Oscar", "Sally", "Marty", "Louis"]
for person in names {
    print (person)
}

If you inserted a break command, you could make this loop exit after running only once like this:

let names = ["Oscar", "Sally", "Marty", "Louis"]
for person in names {
    print (person)
    break
}

This for-in loop would run once, print the name “Oscar,” hit the break command, and exit out of the for-in loop. Of course it’s rather pointless to put a break command inside a for-in loop to stop it prematurely all the time, so it’s more common to use the break command with a branching statement. That way if a certain Boolean value is true, the loop exits prematurely. Otherwise the loop keeps running.

To see how to exit out of the loop prematurely, follow these steps:

  1. Make sure the LoopingPlayground file is loaded in Xcode.
  2. Edit the code as follows:
    import Cocoa

    let employees = ["Fred", "Jane", "Sam", "Kelly"]
    for person in employees {
        if person == "Sam" {
            print (person)
            break
        }
        print (person)
    }

This for-in loop would normally run four times because the “employees” array contains four names. However, as soon as the for-in loop finds the name “Sam,” it prints that name, hits the break command, and prematurely exits out of the for-in loop so it only runs twice as shown in Figure 8-5.

9781484212349_Fig08-05.jpg

Figure 8-5. Using the break command to exit out of a loop prematurely

Using Loops in an OS X Program

In this sample program, the computer picks a random number between 1 and 10. Now the user must guess that number as the computer To keep the user from guessing a number outside the range of 1 and 10, the user interface will let the user choose a value from a slider.

Each time the user guesses incorrectly, a label will display a message that the guess is too high or too low. When the user correctly guesses the number, a loop will print a list of each guess and display it in an alert dialog.

Create a new OS X project by following these steps:

  1. From within Xcode choose File image New image Project.
  2. Click Application under the OS X category.
  3. Click Cocoa Application and click the Next button. Xcode now asks for a product name.
  4. Click in the Product Name text field and type LoopingProgram.
  5. Make sure the Language pop-up menu displays Swift and that no check boxes are selected.
  6. Click the Next button. Xcode asks where you want to store the project.
  7. Choose a folder to store your project and click the Create button.
  8. Click the MainMenu.xib file in the Project Navigator.
  9. Click on the LoopingProgram icon to make the window of the user interface appear as shown in Figure 8-6.

    9781484212349_Fig08-06.jpg

    Figure 8-6. Making the window of the user interface visible

  10. Choose View image Utilities image Show Object Library to make the Object Library appear in the bottom right corner of the Xcode window.
  11. Drag a Horizontal Slider, two Labels, and a Push Button on the user interface and resize them so the user interface looks similar to Figure 8-7.

    9781484212349_Fig08-07.jpg

    Figure 8-7. Creating a basic user interface with two labels, a horizontal slider, and a push button

  12. Click on the top label to select it. Then choose View image Utilities image Show Attributes Inspector. The Attributes Inspector pane appears in the upper right corner of the Xcode window.
  13. Click in the Title text field and type Guess a number.
  14. Click the Center alignment icon as shown in Figure 8-8.

    9781484212349_Fig08-08.jpg

    Figure 8-8. The Attributes Inspector pane for a label

  15. Double-click on the bottom label and type Your guesses = and then press Return.
  16. Double-click on the Push Button, type Guess, and then press Return. Your user interface should look like Figure 8-9.

    9781484212349_Fig08-09.jpg

    Figure 8-9. The completed user interface

  17. Click on the Horizontal Slider to select it and choose View image Utilities image Show Attributes Inspector. The Attributes Inspector pane appears in the upper right corner of the Xcode window.
  18. Select the “Only stop on tick marks” check box.
  19. Click in the text field directly above the “Only stop on tick marks” check box and type 10.
  20. Click in the Minimum text field and type 1.
  21. Click in the Maximum text field and type 10.
  22. Click in the Current text field and type 5 as shown in Figure 8-10.

    9781484212349_Fig08-10.jpg

    Figure 8-10. Changing the Horizontal Slider attributes

With this user interface, the user will use the horizontal slider to choose a number between 1 and 10. If the user guesses a number too high, the label will display “Too High.” If the user guesses a number too low, the label will display “Too Low.”

Each time the user guesses wrong, the bottom label displays the incorrect guess. When the user guesses the correct number, the top label will display “You got it!”

In this example, we’ll need two IBOutlet variables to connect to each label so we can display information on each label. Then we’ll need one IBAction method to connect to the Guess button. That way when the user clicks on the Guess button, the IBAction method can check if the user picked the correct number using the horizontal slider.

We’ll need to write Swift code that chooses a random number between 1 and 10. Then we’ll use a loop to list all the guesses the user made and display those results in an alert dialog.

To connect Swift code to your user interface, follow these steps:

  1. With your user interface still visible in the Xcode window, choose View image Assistant Editor image Show Assistant Editor. The AppDelegate.swift file appears next to the user interface.
  2. Move the mouse over the top label, hold down the Control key, and drag from the top text field to underneath the existing @IBOutlet line in the AppDelegate.swift file as shown in Figure 8-11.

    9781484212349_Fig08-11.jpg

    Figure 8-11. Control-dragging from the top label to the AppDelegate.swift file

  3. Release the mouse and the Control key. A pop-up window appears as shown in Figure 8-12.

    9781484212349_Fig08-12.jpg

    Figure 8-12. The pop-up window for defining an IBOutlet

  4. Click in the Name text field and type messageLabel and click the Connect button. Xcode creates an IBOutlet.
  5. Move the mouse over the bottom label, hold down the Control key, and drag the mouse underneath the @IBOutlet line in the AppDelegate.swift file.
  6. Release the mouse and the Control key. A pop-up window appears.
  7. Click in the Name text field and type guessLabel and click the Connect button. Xcode creates another IBOutlet.
  8. Move the mouse over the horizontal slider, hold down the Control key, and drag the mouse underneath the @IBOutlet line in the AppDelegate.swift file.
  9. Release the mouse and the Control key. A pop-up window appears.
  10. Click in the Name text field and type guessSlider and click the Connect button. Xcode creates another IBOutlet.
  11. You should now have three IBOutlets that represent the two text fields on your user interface:
    @IBOutlet weak var messageLabel: NSTextField!
    @IBOutlet weak var guessLabel: NSTextField!
    @IBOutlet weak var guessSlider: NSSlider!
  12. Edit the underneath the IBOutlets so it looks like this:
    import Cocoa

    @NSApplicationMain

    class AppDelegate: NSObject, NSApplicationDelegate {

        @IBOutlet weak var window: NSWindow!
        @IBOutlet weak var messageLabel: NSTextField!
        @IBOutlet weak var guessLabel: NSTextField!
        @IBOutlet weak var guessSlider: NSSlider!

        var randomNumber : Int
        var guessHistory : String
        var guessNumber : Int
        var guessArray = [Int]()
        var arrayTotal : Int

        override init () {
            self.guessHistory = ""
            self.guessNumber = 0
            self.guessArray = []
            self.arrayTotal = 0
            self.randomNumber = 1 + Int(arc4random_uniform(10))
            // Int(arc4random_uniform(10)) chooses a random number between 0 and 9, so we need to add 1 so it chooses a random number from 1 to 10
        }

        func applicationDidFinishLaunching(aNotification: NSNotification) {
            // Insert code here to initialize your application
        }

        func applicationWillTerminate(aNotification: NSNotification) {
            // Insert code here to tear down your application
        }

    The IBOutlet variables connect to the items on your user interface.

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var messageLabel: NSTextField!
    @IBOutlet weak var guessLabel: NSTextField!
    @IBOutlet weak var guessSlider: NSSlider!

    The next five lines declare variables the entire class AppDelegate can use.

    var guessHistory : String
    var guessNumber : Int
    var guessArray = [Int]()
    var arrayTotal : Int
        var randomNumber : Int

    When you define variables (called properties) inside a class, you need to give them an initial value. That’s the purpose of the override init method:

    override init () {
        self.guessHistory = ""
        self.guessNumber = 0
        self.guessArray = []
        self.arrayTotal = 0
        self.randomNumber = 1 + Int(arc4random_uniform(10))
        // Int(arc4random_uniform(10)) chooses a random number between 0 and 9, so we need to add 1 so it chooses a random number from 1 to 10
    }

    The “self” keyword tells Xcode that all of these variables are defined inside the same class (class AppDelegate). The last line creates a random number between 1 and 10.

    The way this entire program works is that it first creates all its variables. Then it runs the override init method to store initial values in these variables.

  13. Move the mouse over the Guess push button, hold down the Control key, and drag the mouse above the last curly bracket in the AppDelegate.swift file.
  14. Release the mouse and the Control key. A pop-up window appears.
  15. Click in the Connection pop-up menu and choose Action to create an IBAction method.
  16. Click in the Name text field and type checkGuess.
  17. Click in the Type pop-up menu and choose NSButton as shown in Figure 8-13.

    9781484212349_Fig08-13.jpg

    Figure 8-13. Defining an IBAction method

  18. Click the Connect button. Xcode creates a blank IBAction method.
  19. Modify the IBAction checkGuess method as follows:
    @IBAction func checkGuess(sender: NSButton) {
        var userGuess : Int = 0

        // Get guess from horizontal slider
        userGuess = guessSlider.integerValue

        // Store guess in guessArray
        guessArray.append(userGuess)

        if userGuess < randomNumber {
            messageLabel.stringValue = "Too Low"
        } else if userGuess > randomNumber {
            messageLabel.stringValue = "Too High"
        } else {
            messageLabel.stringValue = "You got it!"

            arrayTotal = guessArray.count

            for var i = 0; i < arrayTotal; i++ {
                guessHistory += "Guess (i+1) = (guessArray[i])" + " "
            }
            var myAlert = NSAlert()
            myAlert.messageText = guessHistory
            myAlert.runModal()
        }
        guessLabel.stringValue = guessLabel.stringValue + " (userGuess)"

    }

    Let’s go through this IBAction method so you understand exactly what happens. First, the user needs to use the horizontal slider to pick a number to guess. After choosing a number, the user then needs to click the Guess button, which runs the IBAction method called checkGuess.

    The following line declares an integer variable called “userGuess” and sets its value to 0. This line isn’t absolutely necessary but it does ensure that the “userGuess” variable has an initial value.

    var userGuess : Int = 0

    The next line retrieves the value from the horizontal slider, which is represented by the IBOutlet variable called “guessSlider.” To retrieve the integer that the horizontal slider represents, you have to use the integerValue property. This stores the value from the horizontal slider into the “userGuess” variable that we just declared as an integer variable.

    userGuess = guessSlider.integerValue

    The next line adds the value stored in the “userGuess” variable into the array called guessArray. This array must be defined earlier in your program.

    guessArray.append(userGuess)

    The if-else if statement creates three branches. The first branch runs if the “userGuess” variable is less than the “randomNumber” variable, which must be defined earlier in the program. This displays the text “Too Low” into the label represented by the messageLabel IBOutlet.

    if userGuess < randomNumber {
        messageLabel.stringValue = "Too Low"

    The second branch runs if the “userGuess” variable is greater than the “randomNumber” variable. This displays the text “Too High” into the label represented by the messageLabel IBOutlet.

    } else if userGuess > randomNumber {
        messageLabel.stringValue = "Too High"

    The third branch runs if the “userGuess” variable is neither less than or greater than the “randomNumber” variable, which means that it must be exactly equal to the “randomNumber” variable. This displays the text “You got it!” into the label represented by the messageLabel IBOutlet.

    } else {
        messageLabel.stringValue = "You got it!"

    Then it counts the total number of items stored in the guessArray and puts this value in the “arrayTotal” variable, which must be defined earlier in the program.

    arrayTotal = guessArray.count

    Now it uses a for loop to count from 0 to arrayTotal – 1 (i < arrayTotal) and increments by 1 (i++). It creates a string that stores the guess number, such as Guess 1, and the guess that the user chose in the string variable called “guessHistory,” which must be defined earlier in the program. Notice that you can print numbers in a string by using the () characters where a non-string value appears inside the parentheses. This lets you store non-string values in a string without converting them to a string data type first.

    Also notice that if you simply typed “Guess (i)” then the first string would hold the value “Guess 0” as the first guess. To avoid this, we need to add 1 to the current value of i.

    Notice that the string also contains the characters “ ” at the end. These symbols represent a carriage return and a newline character respectively. These are invisible characters that tell Xcode that if we add more text, it will appear on the next line down.

        for var i = 0; i < arrayTotal; i++ {
    guessHistory += "Guess (i+1) = (guessArray[i])" + " "
    }

    The code inside the for loop uses a compound assignment operator (+=) to add this string to any existing string stored in the “guessHistory” variable. Because of the “ ” characters that create a carriage return and a newline, any new string that gets added will appear on the next line down.

    The next three lines create an alert dialog (NSAlert), stores the string from the “guessHistory” variable into the messageText property of the alert dialog, and then displays the dialog to display how many guesses you took and the numbers you chose in each guess as shown in Figure 8-14.

    var myAlert = NSAlert()
    myAlert.messageText = guessHistory
    myAlert.runModal()

    9781484212349_Fig08-14.jpg

    Figure 8-14. The typical results that appear in an alert dialog

    The last line of the IBAction method simply stores the user’s guesses in the guessLabel IBOutlet, which makes the text appear in the bottom label.

    guessLabel.stringValue = guessLabel.stringValue + " (userGuess)"

    At this point, the program now waits for the user to choose a value in the horizontal slider and click the Guess button.

  20. Choose Product image Run. Xcode runs your LoopingProgram project.
  21. Click on a value in the horizontal slider to guess a number.
  22. Click the Guess push button. If you guess too low or too high, the “Too Low” or “Too High” message appears. Eventually when you guess the correct number, an Alert dialog appears as shown in Figure 8-15.

    9781484212349_Fig08-15.jpg

    Figure 8-15. Displaying an Alert dialog

  23. Click the OK button in the Alert dialog to make it go away.
  24. Choose LoopingProgram image Quit LoopingProgram.

Summary

Loops let you repeat one or more lines of code by running code until a Boolean value becomes false. A while loop checks a Boolean value first, which means it can run zero or more times. A repeat-while loop checks a Boolean value last, which means it can run one or more times.

A for loop lets you specify how many times the loop can run based on a starting value, a Boolean value, and an increment counting operator. A for-in loop can count items in a list automatically.

When creating a loop, always make sure the loop has a way to end. If a loop never ends, it becomes an endless loop, which will make your program appear to freeze and be unresponsive.

Each type of loop has its advantages and disadvantages, but you can always make each loop duplicate the features of the other loops. If you need to exit out of a loop prematurely, you can use the break command along with an if statement.

Loops give your program the power to do repetitive tasks without requiring you to write duplicate commands. Just make sure that your loops always end eventually and that they run the proper number of times before stopping.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset