Appendix A. Conditional Execution and Interface Designing

 

"The only thing that is constant is change"

 
 --Heraclitus

From the time Swift was introduced on stage to the first public release, there have been many changes. This is mainly because Swift has been thrust into the limelight due to being an Apple technology. This has also added the pressure for it to become a mature language. There will definitely be changes in the way Swift works in future. So bear that in mind that the tools around it will reflect the dynamic nature of change. It is not only about Swift; other aspects such as the editor, storyboard, and the debugger could also start to reflect the new changes.

Coming back to the present time, there are a few things that were important to discuss with respect to developing with Xcode, some little gotchas that needed a little getting around. This section actually came up as a result of the rapid changes that were introduced in Xcode 6.

More?.Swift!

From the version of Swift demonstrated at WWDC, to the current version that is available with Xcode 6, Swift has seen changes. Some syntax changed and in some cases the way the command/keyword worked changed. However, there are some important concepts that will always be important.

Each language has its own peculiarities that confuse or keep a beginner at a distance. These include +(void) or -(void) found with Objective-C, or object.method(), and object:method() found in Lua or ? and ! found in Swift.

What do those two symbols mean in the context of Swift code? The answer to that in a sentence is: ! and ? are used to identify optionals. We did discuss that Swift is a typesafe language, which means that the compiler ensures that every variable is of a particular type; if you assign the wrong type, the compiler complains, thereby avoiding a runtime error or a crash.

Consider the following lines of code:

var name:String = "Jayant Varma"
name = "Alexander"    // reassignment works
name = 123.45        // does not work
name = nil        // does not work

We can assign a new value of the same type but not of a different type. Even if the variable was of type Any, you cannot assign nil to it. It is important to note that nil indicates the absence of a value.

Let's look at another scenario; if we were to declare our variables, due to Swift being a typesafe language, you are expected to specify a type. So you cannot simply have code that says:

var theName    //Type annotation missing in pattern

You have to specify it like this:

var theName:String    // Class <classname> has no initializers

However, when you try to compile it, Swift's compiler will throw errors. The compiler expects that the variable is assigned a value via the initialization functions.

With primitives, you can specify default values, such as a blank string or a 0 for numbers:

var theOldBookName:String = ""
var theOldVersionNumber = 0
var theBookName:String = "Xcode Essentials"
var theVersionNumber = 6

Even though we have theOldBookName assigned the value; of an empty string or theoldVersionNumber with 0, it indicates the presence of a value.

With objects, you simply wouldn't create an object to assign a value, you might want to assign a nil value to the variable and then check if the variable was initialized with a value or not. If you try to assign a nil as we saw earlier, an error is thrown. Say we have a function that returns the number of books sold when we pass it the book ISBN. We store that result in a variable like this:

var booksSold = getBooksSoldByISBN("9781430246626")

The only issue with this code is that, if the function could not find the ISBN number or does not have any data on the number of books sold, it returns nil. If we try to assign nil to the variable booksSold, we get an error as the variable cannot hold nil values. This is where optionals come in handy. We can mark a variable with ? at the end of the variable type to tell the compiler that that variable could now have or not have a value (that is, nil):

var booksSold as Int?
booksSold = getBooksSoldByISBN("9781430246626")

We can also display the number of books sold using the value of this variable:

let message = "We sold (booksSold!) books"

The compiler instantly starts to complain because the initializer for string cannot accept nils. We need to unwrap the variable. Unwrapping simply means that it transfers the variable from being of the optional type to the underlying value type. To unwrap, we use the ! symbol:

let message = "We sold (booksSold!) books"

Note

If the ! symbol is used at the beginning of the variable name, it acts as Boolean negation; it unwraps an optional only if used at the end of the variable name.

This is called forced unwrapping. Like the ? symbol informs the compiler that a value might be missing, the ! symbol tells the compiler that a value exists. If you use a ! symbol and the value is nil, you will definitely have a crash. If you run this line in the playground, you will see that an error that occurred as booksSold was nil. Set the value of booksSold to 50000 and you will see:

booksSold = 500000    // getBooksSoldByISBN("9781430246626")
let message = "We sold (booksSold!) books"

It is advised that you should check for nil values before using them, so your code might look something like this:

booksSold = 500000    // getBooksSoldByISBN("9781430246626")
if booksSold != nil {
    let message = "We sold (booksSold!) books"
    println(message)
    }

Now if you comment the booksSold to leave it as nil, it will be fine but that adds a lot of redundant code and checking. Swift offers a better way:

booksSold = 500000    // getBooksSoldByISBN("9781430246626")
if  let numberBooksSold = booksSold {
    let message = "We sold (booksSold!) books"
    println(message)
    }

This assignment using the let statement is called Optional Binding. It serves two purposes: it assigns an unwrapped value to the variable and it works with the if Boolean conditional statement. To the compiler, it instructs:

  1. Unwrap the value of booksSold.
  2. Assign it to the numberBooksSold variable.
  3. If the value was nil or not present, then skip that block; otherwise execute the statements in that block.

We could simplify it further and use the return value from the function as follows:

if let numberBooksSold = getBooksSoldByISBN("9781430246626") {
  let message = "We sold (booksSold!) books"
  println(message)
}

There is one more interesting operator used with Swift, the ?? (double question marks). This is also used with optionals and is called the nil coalescing operator:

var myNilVariable:Int?
println("The  value of myNilVariable is (myNilVariable ?? 100)")

Tip

This is used to provide a default value if the variable does not have a value (that is nil).

You will see that the output displays 100.

Let's say we have another function called getSalesForBookWithISBN that returns a class object. The members of this class that we are interested in are salesNumbers and bookPrice. We could use them like this:

if let bookSales = getSalesForBookWithISBN("9781430246626") {
    if let salesNumbers = bookSales.salesNumbers {
      println("We sold (salesNumbers) books")
    }
}

We could use optional chaining as follows:

if let salesNumbers = getSalesForBookWithISBN("9781430246626")?.salesNumbers {
    println("We sold (salesNumbers) books")
    }
}

Note that we have a ? symbol at the end of the function; this indicates that, if the value returned is nil, then do not check for the remaining properties. So you do not have to first check if a valid class object was returned and then if salesNumbers was not nil. This helps avoid a big mess of nested if let conditional statements. Apple suggests the usage of optional chaining instead of using forced unwrapping, as optional chaining fails gracefully, whereas forced unwrapping can cause runtime errors due to nil values.

Here is another example of how your code can work gracefully with Swift using optionals:

class theClass{
  var students:[String]?
  var className:String?
  var classCode:String?
}
var cp5290 = theClass()

Everything is fine till here, we have an instantiated class object of the theClass type but all of its properties are still nil. Pay special attention to the array called students. If we try to get the number of students from the array using the count function, we could simply use something like this:

if var studentNumbers = cp5290.students?.count {
    println("We have (studentNumbers) students in our class")
}

One last thing to note about declaring optional variables with respect to using a ? or ! symbol is:

var name1:String!
var name2:String?
name1 = "Moe"
name2 = "Larry"
println("The name is (name1) and (name2)")

This outputs The name is Moe and Optional("Larry").

All optionals that are declared with the ? symbol need to be unwrapped for use whereas the variables declared with the ! symbol do not need forced unwrapping. The preceding code line can be used as follows:

println("The name is (name1) and (name2!)")

This outputs The name is Moe and Larry.

With iOS development, you will invariably be using TableViews and you will see a lot of ! and ?; hopefully, you will be able to understand it better after reading this section.

As you use and get familiar with Swift, you will notice the beauty and ease of use that Swift offers. Also note that Swift is an organically growing language and the concepts discussed could change in future versions.

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

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