Chapter    8

Programming Basics in Swift

Swift is an elegant language. It mixes the efficiency of a compiled language with the flexibility and modern features of many scripting languages.

This chapter introduces some of the more common concepts of Swift, such as properties and collection classes. It also shows how properties are used from within Xcode when dealing with user interface elements. This sounds like a lot to accomplish, but Swift, the Foundation framework, and the Xcode tool provide a wealth of objects and methods and a way to build applications with ease.

Using let vs. var

If you have spent much time with Swift, you have seen the word var appear before variable declarations. You may also have seen let before other declarations. The word var is used to define a variable, while the word let is used to define a constant. This means that if you declare a value with let, you will not be able to change the value. The following code defines a constant:

let myName = "Brad"

Once you define a constant, you cannot change the value.

Caution  Xcode 7 will now warn you if you declare a variable and never change its value. It will recommend using let instead of var.

myName = "John"

This will give you an error. It you want to create a mutable or changeable variable, you need to use var. For example, you can do the following:

var myName = "Brad"

myName = "John"

This will not give you any errors because myName is now a variable. This does not relate to only Strings and Ints, but it can also be used with collections and other more complex objects.

Variables give you more flexibility, so why would anyone ever want to use a constant? The quick answer is performance. If you know that you have a value that will not change, the compiler can optimize that value as a constant.

Understanding Collections

Understanding collections is a fundamental part of learning Swift. In fact, collection objects are fundamental constructs of nearly every modern object-oriented language library (sometimes they are referred to as containers). Simply put, a collection is a type of class that can hold and manage other objects. The whole purpose of a collection is that it provides a common way to store and retrieve objects efficiently.

There are several types of collections. While they all fulfill the same purpose of being able to hold other objects, they differ mostly in the way objects are retrieved. The most common collections used in Swift are the array and the dictionary.

Both of these collections can be created as constants or regular variables. If you create a collection as a constant, you must fill it with the objects at the time of creation. It cannot be modified after that point.

Using Arrays

The Array class is like any other collection, in that it allows the programmer to manage a group of objects. An array is an ordered collection, which means that objects are entered in an array in a certain order and retrieved in the same order.

Note  There are some methods for working with arrays that allow you to change the order of the objects or to add an object at a specific location in the array.

The Array class allows an object to be retrieved by its index in the array. An index is the numeric position that an object would occupy in the array. For example, if there are three elements in the array, the objects can be referenced with an index from 0 to 2. Like with most things in Swift and other programming languages, an index starts at 0, not 1. See Listing 8-1.

As you can see, objects in the array can be retrieved via the index. The index starts at 0 and can’t exceed the size of the array minus 1. You can easily calculate the size of the array by sending a count message to the Array object, as shown here:

var entries = myArray.count

In fact, every collection type, in other words, Array and Dictionary, will respond to the count message.

Adding items to the end of an array is simple. You can just call the append method on the array. See Listing 8-2.

Swift provides you with many different methods for adding items to an array. If you want to add multiple objects to an array, you can use the standard += (often called plus equals) operator. Listing 8-3 creates an array and then adds three more String objects to the array on line 2. Notice the new values are in brackets instead of parentheses.

As discussed earlier, an array is actually ordered. The order of the objects in your array is important. There may be times where you need to add an item at a certain position in the array. You can accomplish this with the insert(atIndex:) method, as shown in Listing 8-4.

The array now contains One, Two, Three.

Accessing items in an array is simple. You can use standard square brackets to access an object at a certain position. For example, myArray[0] would give you the first object in the array. If you want to loop through each of the items in the array, you can use something called fast enumeration. Listing 8-5 is an example of fast enumeration.

The magic happens in line 2 of Listing 8-5. You tell Swift to assign each value of myArray to a new variable called myString. You can then do whatever you want to do with myString. In this case, you just print it. It will go through all of the objects in the array without you having to know the total number of objects. This is a fast and effective way to pull items out of an array.

Removing objects from an array is simple too. You can use the removeAtIndex method, as shown in Listing 8-6.

The output from Listing 8-6 will be One, Three. This is because you removed the object with the index of 1. Remember, this is the second object in the array because array indexes always begin at 0.

You have seen how flexible Swift is in letting you interact with arrays. They are powerful collections that you will use on a regular basis as a programmer. This section covered the basics of arrays, but there are many more things arrays can do.

Using the Dictionary Class

The Swift Dictionary class is also a useful type of collection class. It allows the storage of objects, just like the Array class, but Dictionary is different in that it allows a key to be associated with the entry. For example, you could create a dictionary that stores a list of attributes about someone such as a firstName, lastName, and so on. Instead of accessing the attributes with an index like with an array, the dictionary could use a String like "firstName". However, all keys must be unique—that is, "firstName" cannot exist more than once. Depending on your program, finding unique names is normally not a problem.

Here’s an example of how you create a dictionary:

var person: [String: String] = ["firstName": "John", "lastName": "Doe"]

This creates a simple dictionary called person. The next part of the declaration tells the dictionary what kinds of objects the keys and the values will be. In this case, the keys are Strings, and the values are Strings. You then add two keys to the dictionary. The first key is firstName, and that key has a value of John. The second key is lastName, and that has a value of Doe. You can access the values in the dictionary by using a similar notation to arrays.

print(person["firstName"])

This code will print the name Optional("John") since that is the value for the key firstName. The Optional appears in the previous example because the value of a key in a dictionary is an optional value. You can use the same style of code to change the values in a dictionary. Let’s say, for this example, that John now likes to go by Joe instead. You can change the value in the dictionary with a simple line of code.

person["firstName"] = "Joe"

You can add a new key to a dictionary with the same notation.

person["gender"] = "Male"

If you decide you want to remove a key from a dictionary, such as the gender key you just added, you can do so by setting the key to nil.

person["gender"] = nil

Now the dictionary will contain only firstName and lastName. Remember that dictionaries are not ordered. You cannot rely on the order, but there will be times when you need to iterate over a dictionary. This is done in a manner similar to arrays. The main difference is that in an array, you assign one variable, while in a dictionary, you need to assign the key and the value. See Listing 8-7.

This example will print the following:

firstName: John
lastName: Doe

Dictionaries are a great way to organize data that does not need to be ordered. It is also a great way to look up data based on a certain key. They are very flexible in Swift and should be used to organize and optimize your code.

Creating the BookStore Application

You are going to create an app that will demonstrate how to use arrays. You will create a UITableView and use an array to populate the UITableView with data. Let’s start by creating the base application project. Open Xcode and select a new Master-Detail Application project, as shown in Figure 8-1. In this project, you will create a few simple objects for what is to become your bookstore application: a Book object and the BookStore object. You’ll visit instance variables again and see how to get and set the value of one during this project. Lastly, you’ll put the bookstore objects to use, and you’ll learn how to make use of objects once you’ve created them.

9781484214893_Fig08-01.jpg

Figure 8-1. Creating the initial project based on the Master-Detail Application template

  1. Click the Next button and name the project BookStore, as shown in Figure 8-2. The company name is required—you can use any company name, real or otherwise. The example uses com.inn, which is perfectly fine. Make sure the device family is iPhone and that the Language is set to Swift. Do not check the Use Core Data checkbox.

    Note  This type of app would be a good candidate for using Core Data, but Core Data is not introduced until Chapter 11. You will use an array for data storage in this app.

    9781484214893_Fig08-02.jpg

    Figure 8-2. Selecting the product (application) name and options

  2. Once everything is filled out, click the Next button. Xcode will prompt you to specify a place to save the project. Anywhere you can remember is fine—the desktop is a good place.
  3. Once you decide on a location, click the Create button to create the new project. This will create the boilerplate BookStore project, as shown in Figure 8-3.

    9781484214893_Fig08-03.jpg

    Figure 8-3. The source listing of the boilerplate project

  4. Click the plus (+) sign at the lower left of the screen in the Navigator area to add a new object to the project. Choose File. Then choose Source under the iOS section on the left and choose Swift File on the right, as shown in Figure 8-4. It’s also possible to right-click (or Control-click) the Navigation area and then select the New File menu option. There is no difference between this approach and clicking the plus sign—do whatever feels more natural.

    9781484214893_Fig08-04.jpg

    Figure 8-4. Creating a new Swift file

  5. You’re choosing a plain Swift file, which will create a new empty Swift file that you’re going to use for the Book class. After selecting this, click the Next button.
  6. Xcode will ask you what to name your file. Use the name Book. Xcode will also ask to which folder it should save the new file. To keep things simple, choose the BookStore folder in your project. This is where all the other class files for the project are stored.
  7. Double-click the BookStore folder and then click the Create button. You’ll see the main edit window for Xcode and the new file, Book.swift, in the Navigator area, as shown in Figure 8-5.

    9781484214893_Fig08-05.jpg

    Figure 8-5. The empty Swift file

  8. Repeat the previous steps and create a second object called BookStore. This will create a BookStore.swift file. You’ll be using this class later in this chapter. For now, you’ll concentrate on the Book class.
  9. Click the Book.swift file and let’s start defining your new class!

Creating Your Class

You will notice that Xcode does not give you a new class when you create a Swift file. In Objective-C, Xcode used to create the .h and .m files for you. Swift is more flexible, and it is not necessary to have only one class per file. Xcode allows you to add the classes as you want.

Note  It is still a good idea to keep your Swift classes in separate files. This makes organizing and finding classes easier, especially when you’re dealing with large projects.

Let’s create the Book class. Type the following code into the Book.swift file:

class Book {

}

Now you have your class, as shown in Figure 8-6. That is all you need to do to create a class.

9781484214893_Fig08-06.jpg

Figure 8-6. The empty Book class

Introducing Properties

The class is simply called Book. True, you have a class, but it doesn’t store anything at this point. For this class to be useful, it needs to be able to hold some information, which is done with properties. When an object is used, it has to be instantiated. Once the object is instantiated, it has access to its properties. These variables are available to the object as long as the object stays in scope. As you know from Chapter 7, scope defines the context in which an object exists. In some cases, an object’s scope may be the life of the program. In other cases, the scope might be just a function or method. It all depends on where the object is declared and how it’s used. Scope will be discussed more later. For now, let’s add some properties to the Book class to make it more useful.

Listing 8-8 shows the same Book object from before, but now there are three new properties placed inside the brackets, on lines 11 to 13. These are all String objects, which means they can hold text information for the Book object. So, the Book object now has a place to store title, author, and description information.

Accessing Variables

Now that you have some properties, how can you use them? How are they accessed?. Unfortunately, simply declaring a property doesn’t necessarily give you access to it. There are two ways to access these variables.

  • One way, of course, is within the Book object.
  • The second way is from outside the object—that is, another part of the program that uses the Book object.

If you are writing the code for a method within the Book object, accessing its property is quite simple. For example, you could simply write the following:

title = "Test Title"

From outside the object, you can still access the title variable. This is done through the use of dot notation.

myBookObject.title = "Test Title"

Finishing the BookStore Program

With the understanding of properties, you are going to now venture forth to create the actual bookstore program. The idea is simple enough—create a class called BookStore that will be stocked with a few Book objects.

Creating the View

Let’s start by first getting the view ready. If you need a refresher on how to build an interface in Xcode, refer to Chapter 6.

  1. Click the Main.storyboard file in the Navigator area. You will see five scenes in the Main.storyboard file. Navigate to the right to find the detail scene. This will display Xcode’s Interface Builder, as shown in Figure 8-7.

    9781484214893_Fig08-07.jpg

    Figure 8-7. Preparing the Bookstore’s Detail View

  2. By default, when you create a blank Master-Detail application, Xcode adds a label with the text “Detail View content goes here.” Select and delete this Label object because you are going to add your own. You’re going to add some new fields to display some details about a selected book. Since you deleted this control, you also need to remove the code that references it.
    1. In the DetailViewController.swift file, remove the following line:
      @IBOutlet weak var detailDescriptionLabel: UILabel!
    2. In the var detailItem: AnyObject? method, remove the following line:
      self.configureView()
    3. In the DetailViewController.swift file, in the method named configureView, remove the following lines:
      // Update the user interface for the detail item.
      if let detail: AnyObject = self.detailItem {
          if let label = self.detailDescriptionLabel {
              label.text = detail.valueForKey("timeStamp")!.description
          }
      }

    Your DetailViewController.swift file should now look like Figure 8-8.

    9781484214893_Fig08-08.jpg

    Figure 8-8. Modified DetailViewController

  3. Drag some Label objects from the Object Library onto the Detail View, as shown in Figure 8-9. Make sure that the lower Label controls are wider than the default. This is so that they can hold a fairly large amount of text. The two Label objects with the text “Label” in them are the ones you’re going to hook up to hold two of the values from the Book object: Title and Author.

    9781484214893_Fig08-09.jpg

    Figure 8-9. Adding some Label objects

Adding Properties

Next, you’ll add some properties to the DetailViewController class. These properties will correspond to the Detail View’s Label objects.

  1. Click the Assistant Editor icon (it looks like two circles) in the top-right corner of Xcode to open the Assistant editor. Make sure the DetailViewController.swift file is showing in the editor.
  2. Hold the Control key and drag the first blank Label control to the code on the right side, as shown in Figure 8-10. Name the first one titleLabel (see Figure 8-11) and click Connect, and then repeat the process with the second one, naming it authorLabel. This will add two variables to your DetailViewController class, as seen in Listing 8-9, and hook them to the Label controls in the interface.

9781484214893_Fig08-10.jpg

Figure 8-10. Creating variables

9781484214893_Fig08-11.jpg

Figure 8-11. Naming the new variable

Adding a Description

Now you need to add the description to the view. The description is a little different in that it can span multiple lines. For this, you’re going to use the Text View object.

  1. Start by adding the “Description:” label to the view, as shown in Figure 8-12.

    9781484214893_Fig08-12.jpg

    Figure 8-12. Adding a new Label object for the description

  2. Next, add the Text View object to the Detail View, as shown in Figure 8-13. The advantage the Text View object has is that it’s easy to display multiple lines of text. While the Label object can display multiple lines, it’s not as clean as the Text View object.

    9781484214893_Fig08-13.jpg

    Figure 8-13. Adding a Text View to the Detail View

    Note  By default, the Text View control is filled with all kinds of seemingly random text. This text is called Lorem Ipsum text. If you ever need to fill up a page with text, you can find any number of Lorem Ipsum generators on the Web. As for the Text View control, the text can stay as it is since you’ll remove it during runtime. Plus, if it’s cleared, it becomes a little more difficult spotting exactly where the Text View control is on the screen—it’s white on white!

  3. For the program to take advantage of the Text View, you’ll need to create an outlet for it, just like you did for the title and description. Simply Control-drag the Text View to your DetailViewController file, as you did earlier. Name this variable descriptionTextView. The finished variable portion of DetailViewController will look like Listing 8-10.
  4. Notice that the type is UITextView instead of UILabel—this is important.

Caution  As mentioned, it’s important to make the descriptionTextView property a UITextView type. If, for example, it were accidentally made a UILabel object, when trying to connect the Text View from the screen to the outlet, Xcode wouldn’t be able to find the descriptionTextView outlet. Why? Xcode knows that the control is a UITextView and is looking for an outlet that is of type UITextView.

Creating a Simple Data Model Class

For the application to work, it needs to have some data to display. To do this, you’re going to use the BookStore object you created earlier as the data model class. There’s nothing different about a data model class except that its whole purpose is to allow an application to access data via an object.

Modify the BookStore.swift file to look like Listing 8-11.

On line 12, you add a variable that will hold the list of books; the property is simply named theBookStore. Note that theBookStore is an array, which will allow you to add a series of objects, in this case, a set of Book objects.

Next, let’s add the code to the Swift file, BookStore.swift, as shown in Listing 8-12.

In Listing 8-12, lines 14 to 27 define the init method of the object, which is called whenever the object is first initialized. In this method, you initialize the two books you plan to add to your bookstore. Line 15 is where the first Book object is allocated and initialized. Lines 16 to 18 add a title, author, and description to your first book. Finally, line 19 adds the new Book object to the theBookStore array. The important thing to note here is that once the object is added to the array, the code can forget about it; the array now owns that object. Because of this, line 21 is not a problem.

Line 21 allocates a new Book object overwriting the old value. This tells the compiler that you’re no longer interested in using the old value.

Lines 22 to 26 simply initialize and add the second book to the array.

That’s it! That’s all you need to define a simple data model class. Next, you need to modify MasterViewController to access this class so that it can start displaying some data.

Modifying MasterViewController

The simple application has two view controllers: the main view controller, which is called MasterViewController, and a secondary one called DetailViewController. View controllers are objects that simply control the behavior of a view. For the application to start displaying data from the data model, you need to first modify MasterViewController—this is where the navigation of the application begins. The following code is already in place in the template that Xcode has provided. You’re just going to modify it to add your data model.

First you’ll need to modify the MasterViewController.swift file. You need to add a variable to hold the Bookstore object. Listing 8-13 shows that the instance variable is added as a property on line 15.

Now that the BookStore object is initialized, you need to tell MasterViewController how to display the list of books—not the detail, just the book titles. To do this, you’ll need to modify a few methods. Fortunately, Xcode has provided a nice template, so the modifications are small.

MasterViewController is a subclass of what’s called a UITableViewController class, which displays rows of data to the screen. In this case, these are rows of book titles (well, just two for this simple program but a list nonetheless).

There are three main methods that control what and how data is displayed in a UITableViewController.

  • The first isnumberOfSectionsInTableView(_:): Since the application has only one list, or section, this method returns 1.
  • The second istableView(_:numberOfRowsInSection:): In this program, you return the number of books in the bookstore array. Since this is the only section, the code is straightforward.
  • The third method istableView(_:cellForRowAtIndexPath:): This method is called for each row that is to be displayed on the screen, and it’s called one row at a time.

Listing 8-14 details the changes you need to make to get the list of books displaying on the view. The changes start on line 63 in the source file.

Out of all of this code, you need to modify only a few lines. Everything else can stay the way it is. This is one of the advantages of using the Xcode templates. Line 68 simply returned 1; you needed to change it so that it now returns the count of items in the BookStore class.

Line 73 looks a little more complicated. Basically, each line of the UITableView is what is called a cell (a UITableViewCell to be specific). Line 73 sets the text of the cell to the title of a book. Let’s look at that code a little more specifically:

cell.textLabel!.text = myBookStore.theBookStore[indexPath.row].title

First, myBookStore is the BookStore object, which is pretty clear. You’re referencing the array in the BookStore object called theBookStore. Since theBookStore is an array, you can access the book you want in brackets in the indexPath.row. The value indexPath.row specifies which row you’re interested in—indexPath.row will always be less than the total count minus 1. So, calling myBookStore.theBookStore[indexPath.row] returns a Book object. The last part, .title, accesses the title property from the returned Book object. The following code is equivalent to what you just did in one line:

1    var book: Book
2    book = myBookStore.theBookStore[indexPath.row]
3    cell.textLabel!.text = book.title

Now, you should be able to build and run the application and see the two books you created in the data model, as shown in Figure 8-14.

9781484214893_Fig08-14.jpg

Figure 8-14. Running the application for the first time

But, you’re not done yet. You need to make the application display the book when you click one of them. To make this happen, you need to make one last modification to MasterViewController.

The method tableView(_:didSelectRowAtIndexPath:) is called whenever a row is touched on the screen. Listing 8-15 shows the small changes you need to make in order to hook the Detail View to the book data.

If line 49 looks similar to line 73 in Listing 8-14, that’s because it’s basically the same thing. Based on indexPath.row, you select the specific book from the BookStore object and save it in a variable called selectedBook.

On line 51, you take selectedBook and store it in a property called detailItem that is already part of the existing DetailViewController class. That’s all you need to do in MasterViewController. You’ve basically passed off the book to DetailViewController. You’re almost done. Now you need to make a few small modifications to the DetailViewController so that it displays the Book object properly.

Modifying the DetailViewController

Earlier in this chapter, you modified the DetailViewController so that it would display some detail information about a book. In the code you just finished, you modified the MasterViewController so that it passes the selected book to the DetailViewController. Now all that remains is to simply move the information from the Book object in the DetailViewController to the appropriate fields on the screen. All of this is done in one method—configureView—as seen in Listing 8-16.

The configureView method is one of many convenience methods included in the Xcode template and is called whenever the DetailViewController is being initialized. This is where you will move your selected Book object’s information to the fields in the view.

Lines 27 to 29 in the DetailViewController.swift file is where you move the information from the Book object to the view. If you recall, line 51 in Listing 8-15 set the selected book into a property on the DetailViewController called detailItem. Lines 25 to 26 pull that item out into a Book object called myBook.

Lines 36 to 38 simply move each of the Book object’s properties to the view controls you built earlier in the chapter. That’s all you need to do in this class. If you build and run the project and click one of the books, you should see something like Figure 8-15.

9781484214893_Fig08-15.jpg

Figure 8-15. Viewing the book details for the first time

Summary

You’ve reached the end of this chapter! Here is a summary of the topics covered:

  • Understanding collection classes: Collection classes are a powerful set of classes that come with Foundation and allow you to store and retrieve information efficiently.
  • Using properties: Properties are variables that are accessible once the class has been instantiated.
  • Looping with for...in: This feature offers a new way to iterate through an enumerated list of items.
  • Building a Master-Detail application: You used Xcode and the Master-Detail Application template to build a simple bookstore program to display books and the details of an individual book.
  • Creating a simple data model: Using the collection classes you learned about, you used an array to construct a BookStore object and used it as a data source in the bookstore program.
  • Connecting data to the view: You connected the Book object’s data to the interface fields using Xcode.

Exercises

  • Add more books to the bookstore using the original program as a guide.
  • On the Master Scene, remove the Edit button as we will not be using it in this app.
  • Enhance the Book class so it can store another attribute—a price or ISBN, for example.
  • Modify the DetailViewController so that the new fields are displayed. Remember to connect an interface control to an instance variable.
  • Change the BookStore object so that a separate method is called to initialize the list of Book objects (instead of putting it all in the init method).
  • There is another attribute to a UITableViewCell called the detailTextLabel. Try to make use of it by setting its text property to something.
  • Using Xcode to modify the interface, play with changing the background color of the DetailViewController in the storyboard file.

For a tougher challenge:

  • Sort the books in the BookStore object so they appear in ascending order on the MasterDetailView.
..................Content has been hidden....................

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