Swift Development with Cocoa (2015)

Chapter 2. Programming with Swift

The Swift programming language is a new language for writing software for both iOS and OS X. Introduced in June 2014 at Apple’s Worldwide Developers Conference (WWDC), Swift was a surprise to everyone: Apple had managed to develop an entire language (as well as all of the supporting libraries, developer tools, and documentation), and made it work seamlessly with the existing Objective-C language. And on top of that, it’s a really good language.

Swift draws upon an extensive history of language design, and has a number of very cool design features that make developing software easier, simpler, and safer.

In this chapter, you’ll learn how to code in Swift.

The Swift Programming Language

The Swift programming language aims for the following goals:

Safety

Swift is designed to be a safe language. Many of the pitfalls of C, such as accidentally working with null pointers, are much harder to encounter. Swift is very strongly typed, and objects aren’t allowed to be null except under very specific circumstances.

Modernity

Swift contains a large number of modern language features designed to make it easy to express the logic of your code. These include features like pattern-matching switch statements (see Switches), closures (Closures), and the concept of all values being objects that you can attach properties and functions to (Extensions).

Power

Swift has access to the entire Objective-C runtime, and is seamlessly bridged to Objective-C’s classes. This means that you can use Swift right away to write full iOS and OS X apps—you don’t need to wait for anyone to port any features from Objective-C to Swift.

So, what does Swift look like? Here’s an example:

func sumNumbers(numbers: Int...) -> Int { 1

    var total = 0 2

    for number in numbers { 3

        total += number 4

    }

    return total 5

}

let sum = sumNumbers(2,3,4,5) 6

println(sum) 7

This code snippet does the following things:

1

First, a function called sumNumbers is defined. This function takes one or more Int values, which are integers (whole numbers), and returns a single Int. The ... denotes that the function takes a variable number of Int values.

2

Inside the function, the variable total is declared. Note that the type isn’t given—the compiler knows that it stores an Int, because it’s being set to the integer value of zero.

3

Next, a for-in loop starts up, which loops over every number that was sent to the method. Notice again that the type of the number variable isn’t defined—the compiler infers that, given that numbers is an array of Int values, number should itself be an Int.

4

The value of number is added to total.

5

When the loop is complete, total is returned.

6

The function sumNumbers is called with a collection of integers, and the result is stored in the new variable sum. This variable is constant: by defining it with the let keyword, the compiler is being told that its value never changes. Attempting to change the value of a constant is an error.

7

Finally, the value is displayed using the println function, which prints values out to the console.

There are a few interesting things to note here:

§  You usually don’t need to define the type of variables. The compiler will do that for you, based on what values you’re using.

§  Even though the sumNumbers function takes a variable number of parameters, there’s no weird syntax to deal with it (if you’re a C or C++ programmer, you might remember struggling with va_start and friends).

§  Variables that are declared with the let keyword are constants. The language is designed so that any variables that can be a constant should be one, in order to prevent accidental changes later. Importantly, constants in Swift don’t have to be known at compile time. Instead, you can think of them as variables that are only set once.

Playgrounds

The easiest way to learn Swift is to use a playground. Playgrounds are environments that let you write Swift code, and see its results instantly. You don’t need to build and run your code to see the results, and the code doesn’t need to be a part of a larger app. This means that if you want to play around with the language, a function, or even with a piece of a larger app, you don’t need to make it part of an entire app.

NOTE

A lot of this book is written assuming that the code is being run in a playground. You should get used to working in one if you want to follow along!

To start using a playground, you can create one from the “Welcome to Xcode” screen that appears when Xcode starts up (see Figure 2-1).

You can also choose File → New → New Playground and create a new playground from there.

When you create a playground, you’ll end up seeing something that looks like Figure 2-2. On the lefthand side of the window, you can type Swift code. On the righthand side of the window, the result of each line of code that you write will appear.

The Welcome to Xcode screen (click “Get started with a playground” to create a new playground)

Figure 2-1. The Welcome to Xcode screen (click “Get started with a playground” to create a new playground)

An empty playground

Figure 2-2. An empty playground

Variables and Constants

You define a variable in Swift using either the let or var keywords:

var myVariable = 123

let myConstantVariable = 123

NOTE

Comments in Swift are nonexecutable text. You can use comments as a note or reminder to yourself. We use comments often in sample code in this book. They are ignored by the compiler. You can begin a single-line comment with two forward slashes (//), or open a multiline comment using a forward slash and an asterisk (/*) and close it using an asterisk followed by a foward slash (*/).

When you define a variable using var, you’re allowed to change its value. If you define one using let, it’s never allowed to change. Swift encourages you to use constants as much as possible, because they’re safer—if you know that a value can never change, it won’t cause a bug by changing without you knowing about it:

myVariable += 5

// (ERROR: can't change a constant variable)

myConstantVariable += 2

In addition to letting the compiler infer the type of your variables, you can also explicitly tell the compiler what value it should have:

// Explicit type of integer

let anExplicitInteger : Int = 2

Constants in Swift are required to have values. If you define a constant, but don’t give it a value at the time it’s created, the compiler will give you an error:

    let someConstant : Int

    // ERROR: constants must contain values when they're declared

Variables (the nonconstant kind, that is) are allowed to not have a value, as long as you never try to access it. In other words, if you create a variable and don’t give it a value, the only thing you can do with it is to give it a value. After that, you can use it as normal:

    var someVariable : Int

    someVariable += 2

    // ERROR: someVariable doesn't have a value, so can't add 2 to it

    someVariable = 2

    someVariable += 2

    // WORKS, because someVariable has a value to add to

NOTE

Unlike many popular languages, Swift doesn’t require that you end your lines of code with a semicolon. However, if you want to, that’s totally OK.

You can also break your lines of code over multiple lines without problems, like this:

var someVariable =

    "Yes"

The single exception to the rule of not needing to use semicolons is when you want to put multiple statements on a single line. In those cases, you separate the statements with a semicolon:

someVariable = "No"; println(someVariable)

Types

You don’t need to define what type the variable is. Swift will infer its type from its initial value. This means that when you define a variable and set it to the value 2, that variable will be an Int:

// Implicit type of integer

var anInteger = 2

Most types can’t be combined, because the compiler doesn’t know what the result would be. For example, you can’t add a String to an Int value, because the result is meaningless:

// ERROR: Can't add a string to an integer

anInteger += "Yes"

It’s often very useful to have variables that can sometimes have no value. For example, you might have a variable that stores a number to display to the user, but you don’t know what that number is yet. As we’ve seen already, Swift variables need to have a value. One solution might be to use the number zero to represent “no value”; indeed, many languages, including C, C++, Java, and Objective-C do just this. However, this creates a problem: there is no way to distinguish between the value zero and no value at all. What if the value you want to show is actually zero?

To deal with this issue, Swift makes a very clear distinction between “no value” and all other values. “No value” is referred to as nil, and is a different type to all others.

NOTE

In Objective-C, nil is actually defined as a void pointer to 0. This makes it technically a number, which means you can do things like this:

int i = (int)(nil)+2;

// equals 2 (because 0 + 2 = 2)

This isn’t allowed in Swift, because nil and Int are different types.

However, recall that all variables in Swift are required to have values. If you want a variable to be allowed to sometimes be nil, you make it an optional variable. Optional variables are defined by using a question mark (?) as part of their type:

// Optional integer, allowed to be nil

var anOptionalInteger : Int? = nil

anOptionalInteger = 42

Only optional variables are allowed to be set to nil. If a variable isn’t defined as nil, it’s not allowed to be set to the nil value:

// Nonoptional (regular), NOT allowed to be nil

var aNonOptionalInteger = 42

aNonOptionalInteger = nil

// ERROR: only optional values can be nil

You can check to see if an optional variable has a value, by using an if statement:

if anOptionalInteger != nil {

    println("It has a value!")

} else {

    println("It has no value!")

}

When you have an optional variable, you can unwrap it to get at its value. You do this using the ! character.

WARNING

Note that if you unwrap an optional variable, and it has no value, your program will throw a runtime error, and the program will crash:

// Optional types must be unwrapped using !

anOptionalInteger = 2

1 + anOptionalInteger! // = 3

anOptionalInteger = nil

1 + anOptionalInteger!

// CRASH: anOptionalInteger = nil, can't use nil data

If you don’t want to unwrap your optional variables every time you want to use them, you can declare them as unwrapped, like this:

var unwrappedOptionalInteger : Int!

unwrappedOptionalInteger = 1

1 + unwrappedOptionalInteger // = 2

This lets you use their values directly, but can be unsafe (because it lets you get away with not unwrapping them when needed, which can make you forget that they can sometimes be nil). Use this with caution.

You can convert between different types in Swift. For example, to convert an Int to a String, you do this:

let aString = String(anInteger)

// = "2"

Note that not all types can be converted to other types. It depends on the specific types you’re trying to convert between, and the precise value of the thing you’re trying to convert. For example, the string “2” can be converted to an Int, but the string “Hello” can’t.

You also can’t convert types by directly assigning variables—you must explicitly cast. Attempting to assign a value of one type to a variable with another produces an error:

    // ERROR: Can't directly convert between types

    let aString = anInteger

Tuples

tuple is a simple collection of data. Tuples let you bundle multiple values together into a single value:

let aTuple = (1, "Yes")

Once you have a tuple, you can get values out of it:

let theNumber = aTuple.0 // = 1

In addition to using numbers to get the values out of a tuple, you can also apply labels to values inside tuples:

let anotherTuple = (aNumber: 1, aString: "Yes")

let theOtherNumber = anotherTuple.aNumber // = 1

Arrays

Arrays are very easy in Swift. To create an array, you use square brackets ([ and ]):

// Array of integers

let arrayOfIntegers : [Int] = [1,2,3]

Swift can also infer the type of the array:

// Type of array is implied

let implicitArrayOfIntegers = [1,2,3]

You can create an empty array as well, though you need to manually specify its type if you do this:

// You can also create an empty array, but you must provide the type

let anotherArray = [Int]()

NOTE

If you define an array with the let keyword, its contents become immutable (i.e., it’s not allowed to change its contents):

let immutableArray = [42,24]

Once you have an array, you can work with its contents. For example, you can append objects to the end of the array using the append function:

var myArray = [1,2,3]

myArray.append(4)

// = [1,2,3,4]

In addition to appending to the end of the array, you can also insert objects at any point in the array:

myArray.insert(5, atIndex: 0)

// = [5,1,2,3,4]

WARNING

You can’t insert items into an array beyond its bounds. For example, if you tried to insert an item at element 99, it wouldn’t work, and would throw a runtime error (i.e., your program would crash).

You can also remove items from an array. To do this, you indicate the index of the item that should be removed. In Swift, arrays start at index 0, which means that removing the fifth element from the array looks like this:

myArray.removeAtIndex(4)

// = [5,1,2,3]

You can also quickly reverse the contents of an array using the reverse function.

myArray.reverse()

// = [3,2,1,5]

Finally, it’s often useful to know how many items are in an array. You can work this out using the array’s count property:

myArray.count

// = 4

Dictionaries

dictionary is a type that maps keys to values. Dictionaries are useful for when you want to represent a collection of related information.

In a dictionary, you associate a key with a related value. For example, to store information about the crew of the USS Enterprise-D, you could use a dictionary like this:

var crew = [

    "Captain": "Jean-Luc Picard",

    "First Officer": "William Riker",

    "Second Officer": "Data"

];

When you have a dictionary, you can access its contents through subscripting. Subscripting is where you use square brackets ([ and ]) after a variable’s name to describe what you want to get at the contents of that variable. For example, to get the “Captain” value from the crew variable, you do this:

crew["Captain"]

// = "Jean-Luc Picard"

You can also set values in a dictionary using subscripting. For example, to register the fact that “Wesley Crusher” is the ship’s intern:

crew["Intern"] = "Wesley Crusher"

In the previous example, we’ve been talking about a dictionary that uses String values for both its keys and its values. However, it doesn’t have to be set up this way—dictionaries can actually contain almost any value. For example, you can make a dictionary use Int values for both keys and values:

// This dictionary uses integers for both keys and values

var aNumberDictionary = [1: 2]

aNumberDictionary[21] = 23

NOTE

If you mix and match different types in your arrays and dictionaries (e.g., if you make a dictionary that contains both strings and integers as values), then Swift will handle it.

Control Flow

In every program you write, you’ll want control over what code gets executed and when. For this, we’ll make use of if statements, loops, and so on. The syntax for this in Swift is very straightforward, and includes some handy additional features as well.

if statements in Swift are pretty much the same as in any other language, though in Swift there’s no need to wrap the expression you’re checking in parentheses:

if 1+1 == 2 {

    println("The math checks out")

}

// Prints "The math checks out", which is a relief

NOTE

In Swift, the body of all if statements—as well as all loops—is required to be put between two braces ({ and }). In C, C++, Java, and Objective-C, you can omit these braces if you just want to have a single statement in your loop or if statement, like this:

if (something)

    do_something();

However, this has led to all kinds of bugs and security problems caused by programmers forgetting to include braces. So, in Swift, they’re mandatory.

When you have a collection of items, such as an array, you can use a for-in loop to iterate over every item:

let loopingArray = [1,2,3,4,5]

var loopSum = 0

for number in loopingArray {

    loopSum += number

}

loopSum // = 15

NOTE

The number variable used in the for-in loop is implicitly created. You don’t need to define a variable called number to make it work.

You can also use a for-in loop to iterate over a range of values. For example:

var firstCounter = 0

for index in 1 ..< 10 {

    firstCounter++

}

// Loops 9 times

Note the ..< operator on the first line. This is a range operator, which Swift uses to describe a range of numbers from one value to another. There are actually two range operators: two dots and a left-angle-backet (..<) means a range that starts at the first value, and goes up to but does not include the last value. For example, the range 5..<9 contains the numbers 5, 6, 7, and 8.

If you want to create a range that does include the last number, you use three dots and no angle bracket (...). The range 5...9 contains the numbers 5, 6, 7, 8, and 9. You can use an inclusive range operator in for-in loops like so:

var secondCounter = 0

for index in 1 ... 10 { // note the three dots, not two

    secondCounter++

}

// Loops 10 times

Finally, for loops can be used in the same way as other languages—that is, you create an initial state, a condition to test against, and an increment:

var sum = 0

for var i = 0; i < 3; i++ {

    sum += 1

}

sum // = 3

A while loop lets you repeatedly run code while a certain condition remains true. For example:

var countDown = 5

while countDown > 0 {

    countDown--

}

countDown // = 0

while loops check to see if the condition at the start of the loop evaluates to true, and if it does, runs the code (and then returns to the start). In addition to while loops, the do-while loop runs the code at least once, and then checks the condition:

var countUp = 0

do {

    countUp++

} while countUp < 5

countUp // = 5

When working with optional values (see Types for more on this), you can use an if-let statement to check to see if an optional variable has a value, and if it does, assign that value to a constant variable, and then run some code. This can save you quite a few lines of code, while preserving the safety of first checking to see if an optional variable actually has a value to work with.

An if-let statement looks like this:

var conditionalString : String? = "a string"

if let theString = conditionalString? {

    println("The string is '\(theString)'")

} else {

    println("The string is nil")

}

// Prints "The string is 'a string'"

NOTE

You can include the values of variables in strings by using the following syntax:

let myNumber = 3

let myString = "My number is \(myNumber)"

// = "My number is 3"

You can also include the results of expressions, as well:

let myOtherString = "My number plus one is \(myNumber + 1)"

// = "My number plus one is 4"

Switches

switch is a powerful way to run code depending on the value of a variable. Switches exist in other languages, but Swift kicks them into high gear.

To run different code based on the value of an integer, you can use a switch statement like this:

let integerSwitch = 3

switch integerSwitch {

case 0:

    println("It's 0")

case 1:

    println("It's 1")

case 2:

    println("It's 2")

default: // note: default is mandatory if not all

         // cases are covered (or can be covered)

    println("It's something else")

}

// Prints "it's something else"

In Swift, you can use the switch statement to handle more than just integers. You can switch on many things, including String values:

let stringSwitch = "Hello"

switch stringSwitch {

case "Hello":

    println("A greeting")

case "Goodbye":

    println("A farewell")

default:

    println("Something else")

}

// Prints "A greeting"

You can also switch on tuples. This is especially powerful, as you can write cases that run when only one of the components matches your condition:

let tupleSwitch = ("Yes", 123)

switch tupleSwitch {

case ("Yes", 123):

    println("Tuple contains 'Yes' and '123'")

case ("Yes", _):

    println("Tuple contains 'Yes' and something else")

default:

    break

}

// Prints "Tuple contains 'Yes' and '123'"

Finally, you can also use ranges in switches, to create code that runs when the value you’re testing falls between certain ranges:

var someNumber = 15

switch someNumber {

case 0...10:

    println("Number is between 0 and 10")

case 11...20:

    println("Number is between 11 and 20")

default:

    println("Number is something else")

}

// Prints "Number is between 11 and 20"

NOTE

Switches in Swift work a little differently to switches in C and Objective-C. In Swift, the execution of a section in a switch statement doesn’t automatically “fall through” into the next section, which means you don’t need to include a break keyword at the end of your section.

Additionally, switch statements are required to be exhaustive. This means that the switch statement must cover all possible values. If you’re switching using a Bool type, which can either be true or false, you must provide handlers for both values. If you don’t, it’s a compiler error.

However, it’s sometimes not possible to cover all cases. In the case of integers, for example, it’s impossible to write a case for all possible numbers. In these cases, you provide a default case, which is shorthand for “every other possible value.” So, to recap: in Swift, you either provide a case for all possible values, or you provide a default case.

Functions and Closures

In Swift, you define functions to perform tasks with data. Functions let you organize your code into small, repeatable chunks:

func firstFunction() {

    println("Hello")

}

firstFunction()

Functions can return a value to the code that calls them. When you define a function that returns a type, you must indicate the type of the data that it returns, by using the arrow (->) symbol:

func secondFunction() -> Int {

    return 123

}

secondFunction()

You can pass parameters to a function, which it’s able to use to do work. When you define parameters for a function, it is also necessary to define the type of those parameters:

func thirdFunction(firstValue: Int, secondValue: Int) -> Int {

    return firstValue + secondValue

}

thirdFunction(1, 2)

A function can return a single value, as we’ve already seen, but they can also return multiple values, in the form of a tuple. In addition, you can attach names to the values in the tuple, making it easier to work with the returned value:

func fourthFunction(firstValue: Int, secondValue: Int)

    -> (doubled: Int, quadrupled: Int) {

    return (firstValue * 2, secondValue * 4)

}

fourthFunction(2, 4)

When you call a function that returns a tuple, you can access its value by number, or by name (if it has them):

// Accessing by number:

fourthFunction(2, 4).1 // = 16

// Same thing but with names:

fourthFunction(2, 4).quadrupled // = 16

When defining a function, you can give names to the parameters. This is very useful when it might not be immediately obvious what each parameter is meant to be used for. To define parameter names, you do this:

func addNumbers(firstNumber num1 : Int, toSecondNumber num2: Int) -> Int {

    return num1 + num2

}

addNumbers(firstNumber: 2, toSecondNumber: 3) // = 5

When you create names for parameters, you define an external name for the parameter, as well as an internal name. The internal name is how the function refers to the parameter, and the external name is used by the code that calls the function. If you make a function that doesn’t have named parameters, each parameter only has an internal name.

You’ll often find situations where the internal name of a parameter should be the same as the external one. There’s nothing stopping you from typing the same name out twice, but there’s a shorthand that you can use to define a parameter with an external name that’s the same as its internal name—simply place a pound sign (#) in front of the parameter name:

func multiplyNumbers(#firstNumber: Int, #multiplier: Int) -> Int {

    return firstNumber * multiplier

}

multiplyNumbers(firstNumber: 2, multiplier: 3) // = 6

WARNING

When you define an external name for a function parameter, you must use that external name when calling the function. Your code will fail to compile if you don’t.

You can also create functions whose parameters have default values. This means that you can call these functions and omit certain parameters; if you do, those parameters will use the value used in the function’s definition:

func multiplyNumbers2 (firstNumber: Int, multiplier: Int = 2) -> Int {

    return firstNumber * multiplier;

}

// Parameters with default values can be omitted

multiplyNumbers2(2) // = 4

Sometimes, you’ll want to use functions with a variable number of parameters. A parameter with a variable number of values is called a variadic parameter. In these cases, you want a function to handle any number of parameters, ranging from 0 to an unlimited number. To do this, use three dots (...) to indicate that a parameter has a variable number of values. Inside the body of the function, the variadic parameter becomes an array, which you can use like any other:

func sumNumbers(numbers: Int...) -> Int {

    // in this function, 'numbers' is an array of Ints

    var total = 0

    for number in numbers {

        total += number

    }

    return total

}

sumNumbers(2,3,4,5) // = 14

NOTE

When using variable parameters, you can have as many non-variadic parameters as you like. However, note that only the very last parameter in the list can be variadic.

Normally, functions use parameters as input by value, and return values as output. However, if you define a parameter with the inout keyword, you can pass the parameter by reference, and directly change the value that’s stored in the variable. You can use this to swap two variables using a function, like so:

func swapValues(inout firstValue: Int, inout secondValue: Int) {

    let tempValue = firstValue

    firstValue = secondValue

    secondValue = tempValue

}

var swap1 = 2

var swap2 = 3

swapValues(&swap1, &swap2)

swap1 // = 3

swap2 // = 2

When you pass in a variable as an inout parameter, you preface it with an ampersand (&). This is done so that you’re reminded that its value is going to change when you call the function.

Using Functions as Variables

Functions can be stored in variables. To do this, you first declare a variable as capable of storing a function that takes certain parameters, and returns a value. Once that’s done, you can store any function that takes those types of parameters and returns the same type of value in the variable:

var numbersFunc: (Int, Int) -> Int;

// numbersFunc can now store any function that takes two ints and returns an int

// Using the 'addNumbers' function from before, which takes two numbers

// and adds them

numbersFunc = addNumbers

numbersFunc(2, 3) // = 5

Functions can also receive other functions as parameters, and use them. This means that you can combine functions together:

func timesThree(number: Int) -> Int {

    return number * 3

}

func doSomethingToNumber(aNumber: Int, thingToDo: (Int)->Int) -> Int {

    // we've received some function as a parameter, which we refer to as

    // 'thingToDo' inside this function.

    // call the function 'thingToDo' using 'aNumber', and return the result

    return thingToDo(aNumber);

}

// Give the 'timesThree' function to use as 'thingToDo'

doSomethingToNumber(4, timesThree) // = 12

Functions can also return other functions. This means that you can use a function that creates a new function, which you can use in your code:

func createAdder(numberToAdd: Int) -> (Int) -> Int {

    func adder(number: Int) -> Int {

        return number + numberToAdd

    }

    return adder

}

var addTwo = createAdder(2)

addTwo(2) // = 4

A function can also “capture” a value, and use it multiple times. This is a tricky concept, so we’ll go into it in a bit of detail. Consider the following example code:

func createIncrementor(incrementAmount: Int) -> () -> Int {  1

    var amount = 0  2

    func incrementor() -> Int {  3

        amount += incrementAmount  4

        return amount

    }

    return incrementor  5

}

var incrementByTen = createIncrementor(10)  6

incrementByTen() // = 10 7

incrementByTen() // = 20

var incrementByFifteen = createIncrementor(15)  8

incrementByFifteen() // = 15 9

This example does the following things:

1

The createIncrementor function takes an Int parameter, and returns a function that takes no parameters and returns an Int.

2

Inside the function, a variable called amount is created and set to 0.

3

A new function is created inside the createIncrementor function, which takes no parameters and returns an Int.

4

Inside this new function, the amount variable has the incrementAmount parameter added to it, and then returned. Notice that the amount variable is outside of this function.

5

The incrementor function is then returned.

6

The createIncrementor function can then be used to create a new incrementor function. In the first example, one is created with the incremementAmount parameter set to 10.

7

Each time this function is called, it will return a value that’s 10 higher than the last time it was called. The reason it’s doing this is because the function that createIncrementor returned captured the variable amount; every time it’s called, that variable goes up by incrementAmount.

8

The amount variable is not shared between individual functions, however. When a new incrementor is created, it has its own separate amount variable.

9

The second function goes up by 15.

This feature of Swift allows you to create functions that act as generators—functions that return different values each time they’re called.

Closures

Another feature of Swift is that of closures—small, anonymous chunks of code that you can use like functions. Closures are great for passing to other functions in order to tell them how they should carry out a certain task.

To give you can example of how closures work, consider the built-in sorted function. This function takes an array and a closure, and uses that closure to determine how two individual elements of that array should be ordered (i.e., which one should go first in the array).

In addition to the sorted function, which takes an array and returns a sorted version of that same array, there’s also a sort function, which takes an array and changes it into a sorted version:

var sortingInline = [2, 5, 98, 2, 13]

sort(&sortingInline)

sortingInline // = [2, 2, 5, 13, 98]

Note that the variable has an ampersand (&) in front of it.

To sort an array so that small numbers go before large numbers, you can do this:

var numbers = [2,1,56,32,120,13]

var numbersSorted = sorted(numbers, { (n1: Int, n2: Int) -> Bool in

    // Sort so that small numbers go before large numbers

    return n2 > n1

}) // = [1, 2, 13, 32, 56, 120]

A closure, like a function, takes parameters. In the preceding example, the closure specifies the name and type of the parameters that it works with. However, you don’t need to be quite so verbose—the compiler can infer the type of the parameters for you, much like how it can with variables. Notice the lack of types in the parameters for the closure:

var numbersSortedReverse = sorted(numbers, {n1, n2 in

    return n1 > n2

}) // = [120, 56, 32, 13, 2, 1]

You can make it even more terse, if you don’t especially care what names the parameters should have. If you omit the parameter names, you can just refer to each parameter by number (the first parameter is called $0, the second is called $1, etc.).

Additionally, if your closure only contains a single line of code, you can omit the return keyword:

var numbersSortedAgain = sorted(numbers, {

    $1 > $0

}) // = [1, 2, 13, 32, 56, 120]

Finally, if a closure is the last parameter in a function call, you can put it outside the parentheses. This is purely something that improves readibility, and doesn’t change how the closure works:

var numbersSortedReversedAgain = sorted(numbers) {

    $0 > $1

} // = [120, 56, 32, 13, 2, 1]

NOTE

The line breaks in this code are optional, too. You could also do this:

var numbersSortedReversedOneMoreTime = sorted(numbers) { $0 > $1 }

// = [120, 56, 32, 13, 2, 1]

Just like functions, closures can be stored in variables. Once you do that, you can call them, just like a function:

var comparator = {(a: Int, b:Int) in a < b}

comparator(1,2) // = true

Objects

In Swift, as with Objective-C, Java, and C++, you define classes as the templates for your object. Classes in Swift look like this:

class Vehicle {

    var color: String?

    var maxSpeed = 80

    func description() -> String {

        return "A \(self.color) vehicle"

    }

    func travel() {

        println("Traveling at \(maxSpeed) kph")

    }

}

Classes contain both properties and methods. Properties are variables that are part of a class, and methods are functions that are part of a class.

The Vehicle class in this example contains two properties: an optional String called color, and an Int called maxSpeed. Property declarations look the same as variable declarations do in other code:

    var color: String?

    var maxSpeed = 80

Methods in a class look the same as functions anywhere else. Code that’s in a method can access the properties of a class by using the self keyword, which refers to the object that’s currently running the code:

    func description() -> String {

        return "A \(self.color) vehicle"

    }

    func travel() {

        println("Traveling at \(maxSpeed) kph")

    }

When you’ve defined a class, you can create instances of the class to work with. Instances have their own copies of the class’s properties and functions to work with.

For example, to define an instance of the Vehicle class, you define a variable and call the class’s initializer. Once that’s done, you can work with the class’s functions and properties:

var redVehicle = Vehicle()

redVehicle.color = "Red"

redVehicle.maxSpeed = 90

redVehicle.travel() // prints "Traveling at 90 kph"

redVehicle.description() // = "A Red vehicle"

Inheritance

When you define a class, you can create one that inherits from another. When a class inherits from another (called the parent class), it incorporates all of its parent’s functions and properties.

NOTE

In Swift, classes are allowed to have only a single parent class. This is the same as Objective-C, but is different to C++, which allows classes to have multiple parents (known as multiple inheritance).

To create a class that inherits from another, you put the name of the class you’re inheriting from after the name of the class you’re creating, like so:

class Car: Vehicle {

    // Inherited classes can override functions

        override func description() -> String  {

            var description = super.description()

            return description + ", which is a car"

        }

}

Classes that inherit from other classes can override functions in their parent class. This means that you can create subclasses that inherit most of their functionality, but can specialize in certain areas.

To override a function, you re-declare it in your subclass and add the override keyword to let the compiler know that you aren’t accidentally creating a method with the same name as one in the parent class.

In an overridden function, it’s often very useful to call back to the parent class’s version of that function. You can do this through the super keyword, which lets you get access to the superclass’s functions:

        override func description() -> String  {

            var description = super.description()

            return description + ", which is a car"

        }

Initialization and Deinitialization

When you create an object in Swift, a special method known as its initializer is called. The initializer is the method that you use to set up the initial state of an object.

In addition to initializers, you can run code when an object is going away, in a method called its deinitializer. This runs when the retain count of an object drops to zero (see Memory Management), and is called right before the object is removed from memory. This is your object’s final opportunity to do any necessary cleanup before it goes away forever:

class InitAndDeinitExample {

    // Designated (i.e., main) initializer

    init () {

        println("I've been created!")

    }

    // Convenience initializer, required to call the

    // designated initializer (above)

    convenience init (text: String) {

        self.init() // this is mandatory

        println("I was called with the convenience initializer!")

    }

    // Deinitializer

    deinit {

        println("I'm going away!")

    }

}

var example : InitAndDeinitExample?

// using the designated initializer

example = InitAndDeinitExample() // prints "I've been created!"

example = nil // prints "I'm going away"

// using the convenience initializer

example = InitAndDeinitExample(text: "Hello")

// prints "I've been created!" and then

//  "I was called with the convenience initializer"

An initializer can also return nil. This can be useful when your initializer isn’t able to usefully construct an object. For example, the NSURL class has an initializer that takes a string and converts it into a URL; if the string isn’t a valid URL, the initializer returns nil.

To create an initializer that can return nil—also known as a failable initializer—put a question mark after the init keyword, and return nil if the initializer decides that it can’t successfully construct the object:

    // This is a convenience initializer that can sometimes fail, returning nil

    // Note the ? after the word 'init'

    convenience init? (value: Int) {

        self.init()

        if value > 5 {

            // We can't initialize this object; return nil to indicate failure

            return nil

        }

    }

When you use a failable initializer, any variable you store the result in will be optional:

let failableExample = InitAndDeinitExample(value: 6)

// = nil

Properties

Classes store their data in properties. Properties, as previously mentioned, are variables or constants that are attached to instances of classes. Any property that you’ve added to a class can be accessed:

class Counter {

    var number: Int = 0

}

let myCounter = Counter()

myCounter.number = 2

In the previous example, the property is a simple value stored in the object. This is known in Swift as a stored property. However, you can do more with properties, including creating properties that use code to figure out their value. These are known as computed properties, and you can use them to provide a simpler interface to information stored in your classes.

For example, consider a class that represents a rectangle, which has both a width and a height property. It’d be useful to have an additional property that contains the area, but you don’t want that to be a third stored property. Instead, you can use a computed property, which looks like a regular property from the outside, but on the inside is really a function that figures out the value when needed.

To define a computed property, you declare a variable in the same way as you do for a stored property, but add braces ({ and }) after it. Inside these braces, you provide a get section, and optionally a set section:

class Rectangle {

    var width: Double = 0.0

    var height: Double = 0.0

    var area : Double {

        // computed getter

        get {

            return width * height

        }

        // computed setter

        set {

            // Assume equal dimensions (i.e., a square)

            width = sqrt(newValue)

            height = sqrt(newValue)

        }

    }

}

In the previous example, the area is computed by multiplying the width and height together. The property is also settable—if you set the area of the rectangle, the code assumes that you want to create a square, and updates the width and height to both the square root of the area.

Working with computed properties looks identical to working with stored properties:

var rect = Rectangle()

rect.width = 3.0

rect.height = 4.5

rect.area // = 13.5

rect.area = 9 // width & height now both 3.0

When working with properties, you often want to run some code whenever a property changes. To support this, Swift properties let you add observers to your properties. These are small chunks of code that can run just before or after a property’s value changes. To create a property observer, add braces after your property (much like you do with computed properties), and include willSet and didSet blocks. These blocks each get passed a parameter—willSet, which is called before the property’s value changes, is given the value that is about to be set, and didSet is given the old value:

class PropertyObserverExample {

    var number : Int = 0 {

        willSet(newNumber) {

            println("About to change to \(newNumber)")

        }

        didSet(oldNumber) {

            println("Just changed from \(oldNumber) to \(self.number)!")

        }

    }

}

Property observers don’t change anything about how you actually work with the property—they just add additional behavior before and after the property changes:

var observer = PropertyObserverExample()

observer.number = 4

// prints "About to change to 4", then "Just changed from 0 to 4!"

You can also make a property lazy. A lazy property is one that doesn’t get set up until the first time it’s accessed. This lets you defer some of the more time-consuming work of setting up a class to later on, when it’s actually needed. To define a property as lazy, you put the lazy keyword in front of it.

You can see lazy properties in action in the following example. In this code, there are two properties, both of the same type, but one of them is lazy:

class SomeExpensiveClass {

    init(id : Int) {

        println("Expensive class \(id) created!")

    }

}

class LazyPropertyExample {

    var expensiveClass1 = SomeExpensiveClass(id: 1)

    // note that we're actually constructing a class,

    // but it's labeled as lazy

    lazy var expensiveClass2 = SomeExpensiveClass(id: 2)

    init() {

        println("First class created!")

    }

}

var lazyExample = LazyPropertyExample()

// prints "Expensive class 1 created", then "First class created!"

lazyExample.expensiveClass1 // prints nothing, it's already created

lazyExample.expensiveClass2 // prints "Expensive class 2 created!"

In this example, when the lazyExample variable is created, it immediately creates the first instance of SomeExpensiveClass. However, the second instance isn’t created until it’s actually used by the code.

Protocols

protocol can be thought of as a list of requirements for a class. When you define a protocol, you’re creating a list of properties and methods that classes can declare that they have.

A protocol looks very much like a class, with the exception that you don’t provide any actual code—you just define what kinds of properties and functions exist, and how they can be accessed.

For example, if you wanted to create a protocol that describes any object that can blink on and off, you could use this:

protocol Blinking {

    // This property must be (at least) gettable

    var isBlinking : Bool { get }

    // This property must be gettable and settable

    var blinkSpeed: Double { get set }

    // This function must exist, but what it does is up to the implementor

    func startBlinking(blinkSpeed: Double) -> Void

}

Once you have a protocol, you can create classes that conform to a protocol. When a class conforms to a protocol, it’s effectively promising to the compiler that it implements all of the properties and methods listed in that protocol. It’s allowed to have more stuff besides that, and it’s also allowed to conform to multiple protocols.

To continue this example, you could create a specific class called Light that implements the Blinking protocol. Remember, all a protocol does is specify what a class can do—the class itself is responsible for determining how it does it:

class Light : Blinking {

    var isBlinking: Bool = false

    var blinkSpeed : Double = 0.0

    func startBlinking(blinkSpeed : Double) {

        println("I am now blinking")

        isBlinking = true

        // We say self.blinkSpeed here to help the compiler tell

        // the difference between the parameter 'blinkSpeed' and the property

        self.blinkSpeed = blinkSpeed

    }

}

The advantage of using protocols is that you can use Swift’s type system to refer to any object that conforms to a given protocol. This is useful, because you get to specify that you only care about whether an object conforms to the protocol—the specific type of the class doesn’t matter:

var aBlinkingThing : Blinking?

// can be ANY object that has the Blinking protocol

aBlinkingThing = Light()

// Using ? after the variable name checks to see

// if aBlinkingThing has a value before trying to work with it

aBlinkingThing?.startBlinking(4.0) // prints "I am now blinking"

aBlinkingThing?.blinkSpeed // = 4.0

Extensions

In Swift, you can extend existing types, and add additional methods and computed properties. This is very useful in two situations:

§  You’re working with a type that someone else wrote, and you want to add funcitonality to it but either don’t have access to its source code or don’t want to mess around with it.

§  You’re working with a type that you wrote, and you want to divide up its functionality into different sections, for readibility.

Extensions let you do both with ease. In Swift, you can extend any type—that is, you can extend both classes that you write, as well as built-in types like Int and String.

To create an extension, you use the extension keyword, followed by the name of the type you want to extend. For example, to add methods and properties to the built-in Int type, you can do this:

extension Int {

    var doubled : Int {

        return self * 2

    }

    func multiplyWith(anotherNumber: Int) -> Int {

        return self * anotherNumber

    }

}

Once you extend a type, you can call the additional functions and properties that you’ve added. Note that when you extend a type, the functions and properties you define in the extension are added to every instance of that type:

2.doubled // = 4

4.multiplyWith(32) // = 128

NOTE

You can only add computed properties in an extension. You can’t add your own stored properties.

You can also use extensions to make a type conform to a protocol. For example, you can make the Int type conform to the Blinking protocol described earlier:

extension Int : Blinking {

    var isBlinking : Bool {

        return false;

    }

    var blinkSpeed : Double {

        get {

            return 0.0;

        }

        set {

            // Do nothing

        }

    }

    func startBlinking(blinkSpeed : Double) {

        println("I am the integer \(self). I do not blink.")

    }

}

2.isBlinking // = false

2.startBlinking(2.0) // prints "I am the integer 2. I do not blink."

Access Control

Swift defines three levels of access control, which determines what information is accessible to which parts of the application:

Public

Public classes, methods, and properties are accessible by any part of the app. For example, all of the classes in UIKit that you use to build iOS apps are public.

Internal

Internal data is only accessible to the module in which they’re defined. A module is an application, library, or framework. This is why you can’t access the inner workings of UIKit—it’s defined as internal to the UIKit framework. Internal is the default level of access control: if you don’t specify the access control level, it’s assumed to be internal.

Private

Private data is only accessible to the file in which it’s declared. This means that you can create classes that hide their inner workings from other classes in the same module, which helps to keep the amount of surface area that those classes expose to each other to a minimum.

The kind of access control that a method or property can have depends on the access level of the class that it’s contained in. You can’t make a method more accessible than the class in which it’s contained. For example, you can’t define a private class that has a public method:

public class AccessControl {

By default, all properties and methods are internal. You can explicity define a member as internal if you want, but it isn’t necessary:

    // Accessible to this module only

    // 'internal' here is the default and can be omitted

    internal var internalProperty = 123

NOTE

The exception is for classes defined as private—if you don’t declare an access control level for a member, it’s set as private, not internal.

When you declare a method or property as public, it becomes visible to everyone in your app:

    // Accessible to everyone

    public var publicProperty = 123

If you declare a method or property as private, it’s only accessible from within the source file in which it’s declared:

    // Only accessible in this source file

    private var privateProperty = 123

Finally, you can render a property as read-only by declaring that its setter is private. This means that you can freely read and write the property’s value within the source file that it’s declared in, but other files can only read its value:

    // The setter is private, so other files can't modify it

    private(set) var privateSetterProperty = 123

Operators

When you add two integers together in Swift using the + symbol, you’re using an operator. There are a wide variety of different operators built into Swift, and the most common ones are the arithmetic operators (+, -, /, *, etc.). An operator is actually a function that takes one or two values, and returns a value. For example, you could represent the + function like this:

func +(left: Int, right: Int) -> Int {

    return left + right

}

NOTE

The preceding example actually calls itself in an infinitely recursive way, which hangs your app.

Swift lets you define new operators, and overload existing ones for your new types. This means that, if you have a new type of data, you can operate on that data using both existing operators, as well as new ones you invent yourself.

For example, imagine you have an object called Vector2D, which stores two floating-point numbers:

class Vector2D {

    var x : Float = 0.0

    var y : Float = 0.0

    init (x : Float, y: Float) {

        self.x = x

        self.y = y

    }

}

If you want to allow adding these two objects together using the + operator, all you need to do is provide an implementation of the + function:

func +(left : Vector2D, right: Vector2D) -> Vector2D {

    let result = Vector2D(x: left.x + right.x, y: left.y + right.y)

    return result

}

You can then use it as you’d expect:

let first = Vector2D(x: 2, y: 2)

let second = Vector2D(x: 4, y: 1)

let result = first + second

// = (x:6, y:3)

NOTE

For information on how to create your own custom operators, see the “Advanced Operators” section of The Swift Programming Language.

Generics

Swift is a statically typed language. This means that the Swift compiler needs to definitively know what type of information your code is dealing with. This means that you can’t pass a string to code that expects to deal with a date, which is something that can happen in Objective-C.

However, this rigidity means that you lose some flexibility. It’s annoying to have to write a chunk of code that does some work with strings, and another that works with dates.

This is where generics come in. Generics allow you to write code that doesn’t need to know precisely what information it’s dealing with. An example of this kind of use is in arrays: they don’t actually do any work with the data they store, but instead just store it in an ordered collection. Arrays are, in fact, generics.

To create a generic type, you name your object as normal, and then specify any generic types between angle brackets. T is traditionally the term used, but you can put anything you like. For example, to create a generic Tree object, which contains a value and any number of child Treeobjects, you’d do the following:

class Tree <T> {

    // 'T' can now be used as a type

    var value : T

    var children : [Tree <T>] = []

    init(value : T) {

        self.value = value

    }

    func addChild(value : T) -> Tree <T> {

        let newChild = Tree<T>(value: value)

        children.append(newChild)

        return newChild

    }

}

Once a generic type is defined, you can create a specific, nongeneric type from it. For example, the Tree generic type just defined can be used to create a version that works with Ints and one that works with Strings:

// Tree of integers

let integerTree = Tree<Int>(value: 5)

// Can add children that contain Ints

integerTree.addChild(10)

integerTree.addChild(5)

// Tree of strings

let stringTree = Tree<String>(value: "Hello")

stringTree.addChild("Yes")

stringTree.addChild("Internets")

Interoperating with Objective-C

Fortunately, this is very easy to do. For example, to use the UIView class (which is the main focus of Chapter 4), which is written in Objective-C, you can construct an instance just like any other Swift class:

var view = UIView(frame: CGRect(x: 0,y: 0,width: 100,height: 100))

Accessing the properties of an object that’s defined in Objective-C is easy, and works the same way as a Swift object:

view.bounds

Methods in Objective-C get translated from their original form into Swift:

view.pointInside(CGPoint(x: 20, y: 20), withEvent:nil) // = true

Using Objective-C and Swift in the Same Project

If you’re making a new project from scratch, you’ll likely have the opportunity to write all of your code in Swift. However, if you have an existing project written in Objective-C, and want to write code in Swift, you need a way to bridge the two. The same thing applies in reverse, for when you have a project written in Swift and need to add some Objective-C code.

Using Swift Objects in Objective-C

To make objects written in Swift available in Objective-C, you need to add the @objc tag in front of them. For example, if you have a class written in Swift called Cat, you write the class as normal, and prepend @objc in front of its name:

@objc class Cat : NSObject {

    var name : String = ""

    func speak() -> String {

        return "Meow"

    }

}

In your Objective-C code, you import an Xcode-generated header file that makes all of your @objc-tagged Swift code available to Objective-C:

#import "MyAppName-Swift.h"

Once it’s imported, you can use the class as if it had originally been written in Objective-C:

Cat* myCat = [[Cat alloc] init];

myCat.name = "Fluffy";

[myCat speak];

Using Objective-C Objects in Swift

To use classes and other code written in Objective-C in your Swift code, you fill out a bridging header. When you add an Objective-C file to a project containing Swift files, or vice versa, Xcode will offer to create and add a bridging header to your project.

Inside this header, you add #import statements for all of the Objective-C files you want to export to Swift. Then, inside your Swift code, you can use the Objective-C classes as if they had been originally written in Swift.

NOTE

This method is actually how your code accesses the majority of the Cocoa and Cocoa Touch APIs, which are mostly written in Objective-C.

For example, consider a class written in Objective-C, like so:

@interface Elevator

- (void) moveUp;

- (void) moveDown;

@property NSString* modelName;

@end

All you need to do is import the class’s header file into the bridging header that Xcode generates for you:

#import "Elevator.h"

Once that’s done, you can use the class in Swift as if it was originally written in Swift:

let theElevator = Elevator()

theElevator.moveUp()

theElevator.moveDown()

theElevator.modelName = "The Great Glass Elevator"

NOTE

Interoperation between Swift and Objective-C is a large and complex topic, and there are several details that you should know if you plan on making the two work together. Apple’s written an entire book on the topic, Using Swift with Cocoa and Objective-C, which is available for free both online and on the iBooks Store.

Modules

In Swift, just like in Objective-C, code is grouped into modules. When you define a framework or application, all of the code that’s added to it is placed within that target’s module. To get access to the code, you use the import keyword:

import AVFoundation

Memory Management

Objects in Swift are memory managed. When an object is being used, Swift keeps it in memory; when it’s no longer being used, it’s removed from memory.

The technique that Swift uses to keep track of which objects are being used and which are not is called reference counting. When an object is assigned to a variable, a counter called the retain count goes up by 1. When the object is no longer assigned to that variable, the retain count goes down. If the retain count ever reaches 0, that means that no variables are referring to that object, and the object is then removed from memory.

The nice thing about Swift is that this all happens at the compiler level. As the compiler reads your code, it keeps track of when objects get assigned to variables, and adds code that increments and decrements the retain count.

However, this automatic memory management has one potential snag that you need to keep an eye out for: retain cycles.

A retain cycle is where you have two objects that refer to each other, but are otherwise not referred to by any other part of the application. Because those objects refer to each other, their retain count is not zero, which means they stay in memory; however, because no variable in the rest of the application refers to them, they’re inaccessible (and consequently useless).

Swift solves this using the concept of weak references. A weak reference is a variable that refers to an object, but doesn’t change the retain count of that object. You use weak references when you don’t particularly care whether an object stays in memory or not (i.e., your code isn’t the ownerof that object).

To declare a weak reference in Swift, you use the weak keyword, like so:

class Class1 {

    init() {

        println("Class 1 being created!")

    }

    deinit {

        println("Class 1 going away!")

    }

}

class Class2 {

    // Weak vars are implicitly optional

    weak var weakRef : Class1?

}

Working with Strings

In Swift, strings are sequences of Unicode characters. This means that they’re able to store pretty much any character that has ever been a part of a human language, which is great news for making your app translatable to other languages.

Creating a string in Swift is easy. Creating an empty string can be done by creating a string literal with nothing in it:

let emptyString = ""

You can also create an empty string by using the String type’s initializer:

let anotherEmptyString = String()

Checking to see if a string is empty can be done using the isEmpty property:

emptyString.isEmpty // = true

Strings can be combined together, using the + and += operators:

var composingAString = "Hello"

composingAString += ", World!" // = "Hello, World!"

A string is actually a sequence of Character objects, each representing a Unicode character. To loop over every character in a string, you can use a for-in loop:

var reversedString = ""

for character in "Hello" {

    reversedString = String(character) + reversedString

}

reversedString // = "olleH"

To work out how many characters are in a string, you use the countElements function:

countElements("Hello") // = 5

NOTE

The countElements function actually works on any collection, including arrays and dictionaries.

Note that the number of characters in a String is not the same as the number of bytes. Unicode characters can range in size from 1 byte to 4 bytes, depending on their type (emoji, for example, are 4 bytes).

Comparing Strings

To compare two different strings, you just use the == operator. This operator checks the contents of two strings to see if they contain the same characters:

let string1 : String = "Hello"

let string2 : String = "Hel" + "lo"

if string1 == string2 {

    println("The strings are equal")

}

NOTE

In other languages like C and Objective-C, the == operator checks to see if two values are equal, or if two variables refer to the same location in memory. If you really do want to see if two string variables refer to the same object, you use the === operator (note that it’s three equals signs, instead of two):

if string1 as AnyObject === string2 as AnyObject {

    println("The strings are the same object")

}

To change the case of a string, you use the uppercaseString and lowercaseString properties, which return modified versions of the original string:

string1.uppercaseString // = "HELLO"

string2.lowercaseString // = "hello"

Searching Strings

You can check to see if a string has a given suffix or prefix by using the hasPrefix and hasSuffix methods:

if string1.hasPrefix("H") {

    println("String begins with an H")

}

if string1.hasSuffix("llo") {

    println("String ends in 'llo'")

}

Data

In Cocoa, you’ll frequently find yourself working with chunks of arbitrary data that you need to save to or load from disk, or that you’ve downloaded from the network. Cocoa represents these as NSData objects.

You can get an NSData object in a variety of ways. For example, if you have a string that you want to convert to an NSData, you can use the string’s dataUsingEncoding method, like so:

let stringToConvert = "Hello, Swift"

let data = stringToConvert.dataUsingEncoding(NSUTF8StringEncoding)

Loading Data from Files and URLs

You can also load data from a URL or from a file location on disk. If the file is one of the resources built into your project, you first need to work out where on disk it’s being stored; once you have that, you can load its contents into memory.

To get the location of a built-in file, you first use the NSBundle class to determine where a given file is being stored on disk. Once you’ve done that, you construct an NSData object by providing it either a URL or a file path:

// Loading from URL

if let fileURL = NSBundle.mainBundle()

    .URLForResource("SomeFile", withExtension: "txt") {

    let loadedDataFromURL = NSData(contentsOfURL:fileURL)

}

// Loading from a file

if let filePath = NSBundle.mainBundle()

    .pathForResource("SomeFile", ofType: "txt") {

    let loadedDataFromPath = NSData(contentsOfFile:filePath)

}

Serialization and Deserialization

You can also convert an object to data. To do this, you first make an object conform to the NSObject and NSCoding protocols, and then add two methods: encodeWithCoder, and an initializer that takes an NSCoder:

class SerializableObject : NSObject, NSCoding {

    var name : String?

    func encodeWithCoder(aCoder: NSCoder) {

        aCoder.encodeObject(name!, forKey:"name")

    }

    override init() {

        self.name = "My Object"

    }

    required init(coder aDecoder: NSCoder)  {

        self.name = aDecoder.decodeObjectForKey("name") as? String

    }

}

An object that conforms to NSCoding can be converted to an NSData object, and also be loaded from one, via the NSKeyedArchiver and NSKeyedUnarchiver classes. The trick to it is in the encodeWithCoder method, and in the special initializer: in the encodeWithCoder method, you take the NSCoder that’s passed in as a parameter, and store any values that you want to keep in it. Later, in the initializer, you pull those values out.

Converting these objects to and from data is very straightforward, and looks like this:

let anObject = SerializableObject()

anObject.name = "My Thing That I'm Saving"

// Converting it to data

let objectConvertedToData =

    NSKeyedArchiver.archivedDataWithRootObject(anObject)

// Converting it back

// Note that the conversion might fail, so 'unarchiveObjectWithData' returns

// an optional value. So, use 'as?' to check to see if it worked.

let loadedObject =

    NSKeyedUnarchiver.unarchiveObjectWithData(objectConvertedToData)

        as? SerializableObject

loadedObject?.name

// = "My Thing That I'm Saving"

Design Patterns in Cocoa

Cocoa is built around a number of design patterns, whose purpose is to make your life as a developer more consistent and (one hopes) more productive. Three key patterns are the model-view-controller (MVC) pattern, upon which most of Cocoa and Cocoa Touch is built; the delegation pattern, which allows both your code and Cocoa to be highly flexible in determining what code gets run by whom; and notifications, which allow your code to watch for important events that happen within your app.

Model-View-Controller

The model-view-controller design pattern is one of the fundamental design patterns in Cocoa. Let’s take a look at what each of these parts mean:

§  Models are objects that contain data or otherwise coordinate the storing, management, and delivery of data to other objects. Models can be as simple as a string or as complicated as an entire database—their purpose is to store data and provide it to other objects. They don’t care what happens to the data once they give it to someone else; their only concern is managing how the data is stored.

§  Views are objects that work directly with the user, providing information to them and receiving input back. Views do not manage the data that they display—they only show it to the user. Views are also responsible for informing other objects when the user interacts with them. Likewise with data and models, views do not care what happens next—their responsibility ends with informing the rest of the application.

§  Controllers are objects that mediate between models and views, and contain the bulk of what some call the “business logic” of an application—the actual logic that defines what the application is and how it responds to user input. At a minimum, the controller is responsible for retrieving information from the model and providing it to the view; it is also responsible for providing information to the model when it is informed by the view that the user has interacted with it.

For an illustration of the model-view-controller design pattern in action, imagine a simple text editor. In this example, the application loads a text file from disk and presents its contents to the user in a text field. The user makes changes in the text field and saves those changes back to disk.

We can break this application down into model, view, and controller objects:

§  The model is an object that is responsible for loading the text file from disk and writing it back out to disk. It is also responsible for providing the text as a string to any object that asks for it.

§  The view is the text field, which asks another object for a string to display, and then displays the text. It also accepts keyboard input from the user; whenever the user types, it informs another object that the text has changed. It is also able to tell another object when the user has told it to save changes.

§  The controller is the object responsible for instructing the model object to load a file from disk, and passes the text to the view. It receives updates from the view object when the text has changed, and passes those changes to the model. Finally, it can be told by the view that the user has asked to save the changes; when that happens, it instructs the model to do the work of actually writing the file out to disk.

By breaking the application into these areas of responsibility, it becomes easier to make changes to the application.

For example, if the developer decides that the next version of the application should add the ability to upload the text file to the Internet whenever the file is saved, the only thing that must be changed is the model class—the controller can stay the same, and the view never changes.

Likewise, by clearly defining which objects are responsible for which features, it’s easier to make changes to an application while maintaining a clear structure in the project. If the developer decides to add a spellchecking feature to the application, that code should clearly be added to the controller, as it has nothing to do with how the text is presented to the user or stored on disk. (You could, of course, add some features to the view that would allow it to indicate which words are misspelled, but the bulk of the code would need to be added in the controller.)

The majority of the classes described in this chapter, such as NSData, arrays, and dictionaries, are model classes; all they do is store and present information to other classes. NSKeyedArchiver is a controller class; it takes information and performs logical operations on it. NSButton andUITextField are examples of view objects; they present information to the user and do not care about how the data is managed.

The model-view-controller paradigm becomes very important when you start looking at the more advanced Cocoa features, like the document architecture (see Chapter 13) and bindings (see Chapter 11).

Delegation

Delegation is Cocoa’s term for passing off some responsibilities of an object to another. An example of this in action is the UIApplication object, which represents an application on iOS. This application needs to know what should happen when the application moves to the background. Many other languages handle this problem by subclassing—for example, in C++, the UIApplication class would define an empty placeholder method for applicationDidEnterBackground, and then you as a developer would subclass UIApplication and override theapplicationDidEnterBackground method.

However, this is a particularly heavy-handed solution and causes additional problems--it increases the complexity of your code, and also means that if you want to override the behavior of two classes, you need two separate subclasses for each one.[1] Swift’s answer to this problem is built around the fact that an object can determine, at runtime, whether another object is capable of responding to a message.

An object that wants to let another object know that something is going to happen, or has happened, stores a reference to that object as an instance variable. This object is known as the delegate. When the event happens, it checks to see if the delegate object implements a method that suits the event—for delegates of the UIApplication class, for example, the application delegate is asked if it implements the applicationDidEnterBackground method. If it does, that method is called. An object can also be the delegate for multiple objects.

Because of this loose coupling, it’s possible for an object to be the delegate for multiple objects. For example, an object could become the delegate of both an audio playback object and an image picker, and be notified both when audio playback completes and when an image has been captured by the camera.

Because the model-view-controller pattern is built around a very loose coupling of objects, it helps to have a more rigidly defined interface between objects so that your application can know with more certainty how one object expects others to behave.

The specific messages used by delegates are often listed in protocols. For example, if your object wants to be the delegate of an AVAudioPlayer object, it should conform to the AVAudioPlayerDelegate protocol.

Working with delegates in Swift is easy. Imagine you have two classes, and you want one of them to act as the delegate for another:

// Define a protocol that has a function called handleIntruder

protocol HouseSecurityDelegate {

    // We don't define the function here, but rather

    // indicate that any class that is a HouseSecurityDelegate

    // is required to have a handleIntruder() function

    func handleIntruder()

}

class House {

    // The delegate can be any object that conforms to the HouseSecurityDelegate

    // protocol

    var delegate : HouseSecurityDelegate?

    func burglarDetected() {

        // Check to see if the delegate is there, then call it

        delegate?.handleIntruder()

    }

}

class GuardDog : HouseSecurityDelegate {

    func handleIntruder() {

        println("Releasing the hounds!")

    }

}

let myHouse = House()

myHouse.burglarDetected() // does nothing

let theHounds = GuardDog()

myHouse.delegate = theHounds

myHouse.burglarDetected() // prints "Releasing the hounds!"

In Swift, you can check to see if an optional variable is nil by using the ? operator. You can also check to see if an object contains a property or method using the same ? operator.


[1C++’s answer to this problem is multiple inheritance, which has its own problems.