See Swift, See Swift Run - Learn iOS 8 App Development, Second Edition (2014)

Learn iOS 8 App Development, Second Edition (2014)

Chapter 20. See Swift, See Swift Run

As promised, I didn’t start out this book with a dry lesson on Swift. You dove right in and started creating apps—and I think that’s fantastic. The fact that Xcode empowers even novice programmers to design and create quality iOS apps opens a world of possibilities. But you don’t want to stay a novice forever; you don’t get the good seats in the monastery’s dining hall, and there’s never any fan mail. I’m not saying that reading this one chapter will turn you into a Swift guru, but it should definitely up your game.

If you’re struggling at all with Swift or are just relatively new to it, give this chapter a good read. It’s basically a crash course that will put you on a firm footing. This chapter is not intended to be a definitive guide to Swift. It is, after all, only one chapter. Apple has two excellent guides to the Swift language, which I strongly encourage you to download and keep handy. Both of these books are free. Download them through Apple’s iBooks app on your Mac or iOS device.

· The Swift Programming Guide

· Using Swift with Cocoa and Objective-C

These are Apple’s official language guides. The first contains an excellent tutorial as well as a technical description of the language. Think of this chapter as the “Cliff Notes” to The Swift Programming Guide. It’s a fast-paced tour of all the major features, especially ones you’ll use on a daily basis. It’s designed to get you using Swift’s great features today but not pour over its details. In this chapter, you’ll learn the following:

· Learn how classes are declared and objects are created

· Discover Swift’s many shortcuts

· Understand the different kinds of properties

· Use protocols and extensions to augment a class

· Master the use of closures

· Learn how best to use optionals and optional chaining

· Explore arrays, dictionaries, structures, enums, tuples, and a host of other basic data types

· Find out how to avoid some memory management traps

There are no projects for this chapter. Instead, you’ll use an innovative new feature of Xcode called a playground. A playground is a blank page where you can explore the Swift language interactively. Let’s get started, and there’s no better place to start than the beginning.

The (Short) History of Swift

The history of most computer languages stretches back decades. Swift is an outlier, springing like the goddess Athena fully formed from the forehead of Zeus—or, in this case, Apple. The idea for Swift is only a few years old, and until Apple announced it at its World Wide Developers Conference in 2014, almost no one outside of Apple had even heard of it.

Swift incorporates many modern language features but isn’t burdened (at least not yet) with legacy features and syntax. It is a clean, fast, efficient, succinct, safe, modern, and flexible language. Astoundingly, it accomplishes all of this while being binary compatible1 with existing C, Objective-C, and Objective-C++ code. Let me explain some of these concepts briefly, before you get into the nitty-gritty of using Swift.

Swift is a clean language. By clean, I mean that it’s orthogonal and regular—technical terms for being consistent. In a lot of older languages, new features have been bolted on top of other features, which have been bolted on top of the original language. You end up with a patchwork of syntax and rules that aren’t always consistent. In Objective-C, for example, you use one syntax for Objective-C string literals, a different syntax for C string literals, and a third syntax for character literals; and the three types aren’t compatible with one another. Swift eliminates this kind of inconsistency—as far as it’s logically possible.

Swift is fast. Over the past few decades, compiler developers have learned a lot about turning the code you write into efficient machine instructions. One of those lessons is that the more the compiler understands about what the programmer is trying to accomplish, the more efficient it can make the code. Swift’s syntax is designed to subtly communicate that information to the compiler. There’s a tendency for Swift syntax to describe what you want to happen, rather than how you want it to happen. This lets the compiler find the best solution for you.

Swift is also a thoroughly modern language, borrowing innovative features from languages such as Rust, Haskell, Ruby, Python, and others. This is not, however, new. The world of software engineering is strewn with the corpses of computer languages that have introduced all manner of powerful new programming paradigms, most developed by computer scientists. The majority of these have fallen by the wayside because they also failed to meet the performance and compatibility demands of the industry. Swift, by contrast, was first conceived and designed by a “compiler guy.” Chris Lattner, Apple’s lead compiler engineer and one of the principle developers of the LLVM and clang compilers, conceived Swift as a modern language that wouldn’t sacrifice speed or compatibility. In other words, you can finally have your software cake and eat it too.

Most importantly, Swift is a safe language. Its syntax and rules are designed to prohibit many common, and a few uncommon, programming mistakes that are the bane of software developers everywhere. In 2014, the technology world was rocked by a flaw found in one of the core encryption algorithms used to protect data on the Internet. This flaw was the result of a single misplaced semicolon (;) on a line of C code, a classic mistake that C programmers have been making since the beginning of the language. Swift’s syntax is carefully designed to help you avoid making these kinds of simple, yet sometimes catastrophic, mistakes. (That doesn’t mean you can’t write buggy software; it’s just less likely to be Swift’s fault.)

Finally, Swift is concise without being terse. By concise, I mean that the same program in Swift is likely to be shorter than the same code written in C, C++, Java, C#, or Objective-C. This means your code is less voluminous, easier to read, and easier to write. That, indirectly, means you have less to write, and what you do write is easier to understand. The following Objective-C statement sorts an array of Person objects into ascending order by date of birth:

[people sortUsingComparator:^NSComparisonResult(id l, id r) {
Person *p1 = (Person*)l;
Person *p2 = (Person*)r;
return [p1.birthdate compareDate:p2.birthdate];
}];

Compare that to the same code in Swift:

people.sort { $0.birthdate < $1.birthdate }

For contrast, a terse language (such as Perl) can accomplish things with astoundingly little code but sacrifices readability. For example, the following is a complete program in Perl:

print("".(($line=join("",<>))=~s/.*\n/$h{$&}++?"":$&/ge,$line));

If you read that statement and said “Oh yeah, that’s reading a file and eliminating all of the duplicate records using a hash table,” then you’re a natural-born computer language god who can skip the rest of this chapter.

Now that the gods have left the building, I should point out that Swift is very much a work in progress. The version of Swift I’m writing about in October 2014 is, in many ways, substantially different from the one released at Apple’s WWDC only a few months earlier. And I expect Swift to continue to change, sometimes dramatically, as it evolves. So, take what you read here with a grain of salt and read up on the latest improvements to Swift. A good place to start is the Swift blog at http://developer.apple.com/swift/blog/. Yes, Swift has a blog.

Classes

You’ve seen this a hundred times so far, and I explained it in Chapter 6, but here is again, in all its glory. A class in Swift is declared by a class directive, as follows:

class ClassName: SuperClassName, ProtocolName {
private var instanceVariable: Int = -1
func instanceFunction(firstParam: Int, secondParam: Int) -> Bool {
return firstParam >= secondParam
}
}

Here are the salient points:

· The class declaration informs the compiler that you’re declaring a new class, what class it inherits from, what protocols it adopts, what properties it has, and what methods (instance functions) it defines.

o The superclass is optional. If your class doesn’t inherit from an existing class, the superclass name can be omitted.

o Protocols are optional. If your class doesn’t adopt any protocols, the list of protocol names can be omitted.

· The body of your class consists of its properties and functions. Anything declared inside the class statement belongs to this class.

· You can optionally insert access control directives (public, private, or internal) before property or function declarations.

Tip By convention, type names start with a capital letter (MyClass, ViewController, Weekday, and so on). Variable names start with a lowercase letter (dataSource, frame, userInteractionEnabled, and so on).

Most of this should all make sense to you by now. The only keywords not mentioned in this book so far are the access control directives. The visibility of a variable or function determines what code is allowed access to them. Table 20-1 lists the choices.

Table 20-1. Access Control Directives

Directive

Meaning

public

Any code can use this property or function.

internal

Only the code in the app or framework where this class is defined can access this property or function.

private

Only functions in this class may access this property or function.

When I say “access,” I mean refer to that property, or call that function, in any statement. The internal keyword is only interesting when developing frameworks. It’s a middle ground between private and public. For code in the same app or framework, it acts like public access. For code outside the app or framework, it acts like private access.

Note If you omit the access control, it defaults to internal. Almost all of the time this means that your properties and functions will be public. If you start using your classes in frameworks, you’ll need to explicitly declare your public interfaces using the public keyword.

Playgrounds

But don’t take my word for it. Create a new playground and try any of the code snippets in this chapter, or anything else you want to try in Swift. A playground is an interactive Swift document that simultaneously compiles and runs whatever code you put there.

From the Xcode File menu, choose the New image Playground command, or just create a new file and choose the Playground template. Give the playground a file name and save it somewhere. You now have a blank slate to try Swift features, as shown in Figure 20-1.

image

Figure 20-1. Swift playground

You type in code on the left, and the results appear on the right. The right-hand pane will show you what values were set, what an expression evaluates to, how many time a loop ran, the last value returned from a function, and so on. Change your code, and everything is evaluated again.

There are playground files for most of the sections in this chapter. They contain the code snippets described here, along with additional examples and comments. The playgrounds for this chapter can be found in the Learn iOS Development Projects image Ch 20 folder, and all have fairly obvious names. The playground for this section is Classes.playground.

Properties

A property is a value that belongs to an instance of that class—that is, an object. There are two kinds of properties: stored and computed. A stored property allocates variable space within the object to retain a value. You declare a stored property as follows:

class ClassStoringProperties {
let constantProperty: String = "never changes"
var variableProperty: Int = 1
}

A let defines a constant (immutable) property. A var defines a variable (mutable) property. You can obtain the value of either, but you can only change (mutate) the value of a var.

A property has a name, a type, and an optional default value. You can omit the type or the value. If you omit the type, the type is inferred from the value you’re setting it to, as follows:

let constantProperty = "never changes"
var variableProperty = 1

These two properties are identical to the previous two. Their types (String and Int) were inferred from the types of their default values. If you don’t specify the type of a property, its type will be the type of the value you set it to.

In Swift, all variables must be initialized when they are declared. It is strictly forbidden to declare a variable or constant that is not set with an initial value. This eliminates a whole class of common programming mistakes that arise from uninitialized variables.

Within a class (or structure) you can bend this rule a little. You can declare a stored property that doesn’t have a default value, as long as you provide its initial value when the object is initialized. In a class, it’s legal to write the following:

var uninitializedProperty: Int

If you do this, you must provide an initializer function that sets uninitializedProperty to a value before the object can be used. I cover initializer requirements a little later in this section.

Computed Properties

Computed properties, sometimes called synthetic properties, are property values that are calculated by a block of code. They have no variable storage associated with them, but they often use other stored properties in their calculations. The following is an example of a computed property:

class ClassCalculatingProperties {
var height: Double = 0.0
var width: Double = 0.0
var area: Double {
get {
return height*width
}
set(newArea) {
width = sqrt(newArea)
height = width
}
}
}

This class has two stored properties and one computed property. The computed area property can be used just like any other property, as follows, but its value when retrieved is determined by the code in the get block of the property. This is called the property’s getter. The getter is required.

let calculatingObject = ClassCalculatingProperties()
calculatingObject.height = 9.0
calculatingObject.width = 5.0
let area = calculatingObject.area /* area = 45.0 */

If you want the property to be mutable, you can also supply a setter function, as shown. The parameter to the set(newArea) code block contains the value to be set. If you omit the setter, the property is read-only. It also means you can use a shorthand syntax that drops the get { ... }portion, as follows:

var area: Double { return height*width }

Even if the value returned by a read-only computed property never changes, you must still declare the property using the var keyword. The logic is that the value could change—there’s no way for Swift to know otherwise—so it must be declared to be a variable.

Property Observers

You can also attach code to a stored property. When a stored property is set, you have two opportunities to execute code: a willSet and a didSet code block. You declare these immediately after the stored property, much like a computed property, as follows:

class ObservantView: UIView {
var text: String = "" {
didSet(oldText) {
if text != oldText {
setNeedsDisplay()
}
}
}
}

In this example, the code in the didSet(oldText) block executes whenever the text property is assigned. The didSet code block executes after the property has been updated; the parameter contains the previous value. Here, it’s used to determine whether the string actually changed and redraws the view only if it did.

Similarly, the willSet code block executes before the stored property is updated. Its single parameter is the new value to be set. If you want to override the value being set, change the property’s value in the didSet function to something other than what was set.

Tip When writing set, willSet, and didSet code blocks, you can either choose a name for the single parameter or leave it out. If you leave it out, Swift supplies a parameter named newValue, newValue, or oldValue (respectively) for use in your code.

You can’t attach code that executes when a stored property is read. And you can’t attach property observers to a computed property. The latter would be redundant since the setter code can do anything a property observer could.

Methods

A function in a class is called a method, an instance method, an instance function, or sometimes a member function. It’s a function that runs in the context of an object. You declare methods as a function in the body of the class, as follows:

func pokeUser(name: String, message: String) -> Bool {
return true
}

This method is passed two parameters and returns a Boolean value. You would invoke it with a statement such as the following:

let result = object.pokeUser("james", message: "Is that an ice cream truck I hear?")

If the function does not return a value, omit the return type that follows the parameter list (-> ReturnType).

Class Methods

A class method is like a global function, but it belongs to the class. A class method does not execute in the context of an object. You declare a class method using the class keyword, as follows:

class GoldenAge {
class func timeRemaining() -> Double { ...

You call a class method using the class name (instead of an object reference), as follows:

let remaining = GoldenAge.timeRemaining()

Because a class method does not execute in the context of an object, you can’t refer to any property or instance function of the class directly. This even applies to constants.

Class methods are often used to provide access to global resources, as getters for singletons, or as factory methods to create configured objects.

Parameter names

Every parameter in a function has two names: an external parameter name and a local parameter name. The following function has three parameters with six names:

func poke(user name: String, say message: String, important priority: Bool) -> Bool {
if priority {
sendMessage(message, toPerson: name)
return true
}
return false
}

In this example, every parameter has both an external and a local parameter name, and they are all different. In the function’s code, you use the local parameter names (name, message, and priority) to refer to their values.

When calling the function, you use the external parameter names (user, say, important). The following statement will call that function:

poke(user: "james", say: "Wouldn't some ice cream be great?", important: true)

Optional Parameter Names

Both local and external parameter names are optional. If there is no external parameter name, the call’s argument list includes only the value. The following function and function call demonstrate this:

func pokeUser(name: String, message: String) { ... }

pokeUser("james", "I swore I heard the ice cream truck!")

If you omit the external parameter name, Swift may use the local parameter name as the external parameter name. For example, the following two method declarations are identical:

class ExternalNamesInAClass {
func pokeUser(name: String, message: String) { ... }
func pokeUser(name: String, message message: String) { ... }
}

In both functions, the initial parameter has no external name, while the last one does. In the first function, Swift used the local name of the last parameter as its external name. Both of these functions would have to be called as follows:

pokeUser("james", message: "I'm going to get ice cream.")

So, why does this happen? Swift’s expectations about external parameter names vary based on the context of the function as follows:

· A function declared outside a class, structure, or enumeration (sometimes called a global function) is not expected to have any external parameter names. If you declare an external name, it will be required to call the function. If you omit it, that argument will be bare.

· A method (a function declared in a class) does not expect an external name for the first parameter but does expect one for all remaining parameters. If you omit an external name, the local name will be used as the external name starting with the second parameter.

· If your parameter provides a default value (see the section “Default Parameter Values”), Swift expects it to have an external name.

· A class or structure initialization function (init()) is expected to have external names for all parameters. If you omit any, the local name is used as the external name.

The first rule makes Swift functions consistent with C, Java, and similar languages. If you don’t declare external parameter names, your function calls will look like those legacy languages. You have the option of using Swift’s more expressive named parameters, but it’s not a requirement.

The second rule is intended to make adopting Objective-C’s method naming convention easy within classes. Objective-C doesn’t make a distinction between function and parameter names. An Objective-C method name is really just a sequence of tokens that separate the parameters. Consequently, the first token of an Objective-C method typically names the first parameter as well, as in the setBool(_:,forKey:) method (or -setBool:(bool)b forKey:(NSString)key, as it’s written in Objective-C). The first parameter is the Boolean value, already identified in the function’s name. You wouldn’t want to write setBool(bool: true, forKey: "key").

The final rule is to make it easy to create multiple initializers without getting them mixed up. All functions must have a unique signature. Since the function name of all initializers is init, Swift must have unique external parameter names to distinguish between them.

Parameter Name Shortcuts

If you want to specify an external parameter (where Swift does not enforce one) and your external and local parameter names are the same, you can use one name for both by using a # (pound sign or hash) for the external name. The following two function declarations are identical:

func function(parameter parameter: Int)
func function(# parameter: Int)

Conversely, you can force Swift to not use an external parameter name—in those circumstances where it normally would—by replacing the external name with an _ (underscore) character. You can suppress the external parameter name in the poke(_:,message:) function by writing it as follows:

func poke(name: String, _ message: String)

Now you would call this function simply as object.poke("james","What flavor?").

You can also ignore the local parameter name. Do this when you have no interest in that parameter. For example, the UIControl classes send actions by calling a method whose single parameter is the control object that caused the action. A typical action method looks like this:

@IBAction func sendPoke(sender: AnyObject)

Quite often, the action method has no use for the sender parameter. You can signal your disinterest by replacing the local parameter name with an _ (underscore) character, as follows:

@IBAction func sendPoke(_: AnyObject)

The parameter is still there, and the caller is still required to supply it, but the function’s code ignores it.

Default Parameter Values

You can supply a default value for one or more parameters. If you do, you can optionally omit that parameter from the function call and the function will receive the default value. You assign default values in a function’s declaration, as follows:

func pokeUser(name: String, message: String = "Poke!", important: Bool = false )

The second and third parameters have default values. Either or both can be omitted from a function call. If you omit the argument in a call, the parameter will be set to the default value. All four of the following statements call this function:

defaulter.pokeUser("james")
defaulter.pokeUser("james", message: "Where's my ice cream?")
defaulter.pokeUser("james", important: true)
defaulter.pokeUser("james", message: "The ice cream is melting!", important: true)

For clarity, parameters with default values should have external names. Swift assumes this and will use the local name as the external name if you omit it. To avoid ambiguity, any subsequent parameters should also have external names.

Inheritance

A class can inherit from another class. When it does so, it acquires all of the properties and methods of its superclass. The class then augments this foundation with additional properties and methods.

A class can override a method of its superclass. When you do this, you must prefix the method with the override keyword, as follows. This prevents you from accidentally overriding a method because you happened to pick a function name that was already implemented.

class BaseClass {
var lastUserPoked: String = "james"
func pokeUser(name: String) {
sendMessage("Poke!", toUser: name)
lastUserPoked = name
}
}

class SubClass: BaseClass {
override func pokeUser(name: String) {
println("someone poked \(name)")
}
}

A method has a special super variable that refers to the methods and properties of its superclass. Use the super variable to invoke the superclass’ method, instead of the one overridden by your class, as follows:

class SubClass: BaseClass {
override func pokeUser(name: String) {
super.pokeUser(name)
println("someone poked \(name)")
}
}

Overriding Properties

You can also override any property with a computed property. The property you’re overriding may be a stored property or another computed property. Again, you use the override keyword to signal your intent. In the following example, the subclass is creating a computed propertylastUserPoked that overrides the stored property (lastUserPoked) defined in the base class.

class SubClass: BaseClass {
override var lastUserPoked: String {
get {
return super.lastUserPoked
}
set {
if newValue != lastUserPoked {
println("caller is poking a different user")
}
super.lastUserPoked = newValue
}
}
}

Notice how the computed property uses the super.lastUserPoked syntax to access the stored property defined in the base class.

Alternatively, you can override a property observer, as follows:

override var lastUserPoked: String {
didSet {
...
}
}

The inherited property can be either a stored or computed property, but it must be mutable; property observers are only executed when the value is set.

Blocking Inheritance

If you want to cut out any heirs to your class, methods, or properties, use the final keyword. The following class defines a property and method that are final:

class ClassWithLimitedInheritance {
final var trustFundName: String = "Scrooge McDuck"
final func giveToCharity(amount: Double) {
if amount > 2.00 {
println("Too much!")
}
}
}

You can create a subclass of ClassWithLimitedInheritance and extend it, but you cannot override its trustFundName property or its giveToCharity(_:) method. If you want to prohibit all subclassing, add the final keyword to the class itself, as follows:

final class EndOfTheLine: ClassWithLimitedInheritance { ...

Object Creation

You create a Swift object by writing the class’s name as if it were a function call. The following statement creates a new ClassCalculatingProperties object and assigns it to calculatingObject:

let calculatingObject = ClassCalculatingProperties()

This syntax allocates a new object and invokes one of the class’s initializer functions. In this example, that was init()—the initializer with no parameters. You can write your own class initializers. You write one just like a member function with the exceptions that you omit the funckeyboard, the name of the function is always init, and it does not return a value, as follows:

class SimpleInitializerClass {
var name: String
init() {
name = "james"
}
}

Every class must have at least one initializer function, else how are you going to create objects? In the following class, all stored properties have default values, and the class doesn’t declare any initializers of its own. In this situation, Swift creates an init() initializer for you.

class AutomaticInitializerClass {
var name = "james"
var superUser = true
// init() supplied by Swift
}

You can define as many initializers as you want. They can also include default parameter values, as shown here:

class IceCream {
var flavor: String
var scoops: Int = 1
init() {
flavor = "Vanilla"
}
init(flavor: String, scoops: Int = 2) {
self.flavor = flavor
self.scoops = scoops
}
}

Tip If a local variable name has the same name as a property, use the self variable to distinguish between them. flavor refers to the local parameter. self.flavor refers to the object’s flavor property.

Your initializers are distinguished by their external parameter names (since they all have the same function name). Swift chooses the initializer based on the parameter names, as follows:

let plain = IceCream()
let yummy = IceCream(flavor: "Chocolate")
let monster = IceCream(flavor: "Rocky Road", scoops: 3)

Note All swift values are created using the same syntax. The expression CGFloat(1.0) creates a new CGFloat value equivalent to the Double constant 1.0. The expression Weekday(rawValue: 1) creates an enumeration value equal to .Monday, and so on.

Subclass Initializers

If your class is a subclass, your initializer must explicitly call one of the superclass’ initializers. In the following subclass, the initializer sets up its properties and then invokes the superclass’ initializer so the superclass can initialize its properties:

class IceCreamSundae: IceCream {
var topping: String
var nuts: Bool = true
init(flavor: String, topping: String = "Caramel syrup") {
self.topping = topping
super.init(flavor: flavor, scoops: 3)
}
}
}

Safe Initialization

Swift consistently enforces the rule that you cannot use any value, class, or structure until every variable has been initialized. Swift also lets you defer the initialization of stored properties to your initializer function. This can lead to a bit of a chicken-and-egg problem.

Let me demonstrate the problem by adding an addCherry() function to the IceCream class and then override it in the IceCreamSundae class, as follows:

class IceCream {
...
init(flavor: String, scoops: Int = 2) {
self.flavor = flavor
self.scoops = scoops
addCherry()
}
func addCherry() {
}
}

class IceCreamSundae: IceCream {
...
init(flavor: String, topping: String = "Caramel syrup") {
super.init(flavor: flavor, scoops: 3) // <-- invalid initializer
}
override func addCherry() {
if topping == "Whipped Cream" {
...
}
}
}

Consider how an IceCreamSundae object gets created. When the initializer for IceCreamSundae starts to execute, the topping property is not yet initialized because it has no default value. You can’t call the superclass initializer (super.init(flavor:,scoops:)) yet because there’s a possibility that it might call the addCherry() function (which you overrode), which could then access the uninitialized toppings property.

To solve this dilemma, Swift requires all initializers to perform their work in three phases, in the following order:

1. Initialize all stored constants and variables, either explicitly or by relying on the property’s default value.

2. Call the superclass initializer to initialize the superclass.

3. Perform any additional setup that would involve calling methods or using computed properties.

The first thing the IceCreamSundae initializer must do is to ensure that all of its properties are initialized. The correct way to write the IceCreamSundae initializer is as follows:

class IceCreamSundae: IceCream {
...
init(flavor: String, topping: String = "Caramel syrup") {
self.topping = topping
super.init(flavor: flavor, scoops: 3)
}

The single self.topping = topping statement satisfies the requirement of the first phase. The topping property does not have a default value and must be explicitly set. The nuts property has a default value; if you don’t set it to something else, Swift will set it to true for you. At this point, all subclass properties have been initialized.

Note Property observers are never executed during object initialization.

This is also the one place in Swift where you can set immutable constants. Even if a property is declared as a constant (let preferDarkChocolate = true), you can set it during the first phase of object initialization.

The second phase must call the superclass initializer. This will initialize all of its properties, its superclass’s properties, and so on.

When the superclass initializer returns, the object is fully initialized. It is now safe to call any member function or use any property to prepare the object for use.

Your initializer might be missing some of these phases.

· If the class has no stored properties or all stored properties have default values, the first phase isn’t needed.

· If the class doesn’t have a superclass, there’s no superclass initializer to call, and no second phase.

· If the class doesn’t have any initialization beyond Swift’s requirements, there won’t be a third phase.

Convenience Initializers

The initializers I’ve described so far are called designated initializers. A designated initializer is an initializer that implements the three phases outlined in the previous section.

You can also create convenience initializers. A convenience initializer makes it easier to create objects by providing a simplified interface but defers the important work of initializing the object to another initializer in the same class. You declare a convenience initializer with theconvenience keyword. The following code adds a convenience initializer to the IceCreamSundae class:

convenience init(special dayOfWeek: Weekday) {
switch dayOfWeek {
case .Sunday:
self.init(flavor: "Strawberry", topping: "Whipped Cream")
case .Friday:
self.init(flavor: "Chocolate", topping: "Chocolate syrup")
default:
self.init(flavor: "Vanilla")
}
}

You can now create the ice cream sundae du jour with the following statement:

let sundaySundae = IceCreamSundae(special: .Sunday)

Note the use of self.init(...) to call another initializer in the same class. The called initializer must be in the same class and be either a designated initializer or another convenience initializer that eventually calls a designated initializer.

Inheriting Initializers

Initializer inheritance gets a little tricky. For the complete story, refer to The Swift Programming Guide in iBooks, but here are the basic rules:

· If your subclass doesn’t define any initializers of its own and all of its stored properties have default values, the subclass inherits all of the initializers from its superclass. (Technically, Swift generates all of the designated initializers for you.)

· If your subclass overrides an initializer, you must prefix it with an override keyword, just like a method or property.

· If your subclass declares any uninitialized stored property variables or constants, you are required to implement designated initializers to set those values.

· If your subclass implements any of its own initializers, it won’t automatically inherit any designated initializers. If you want the same designated initializers in your subclass, you must override and re-implement them all.

· You only inherit convenience initializers that call a designated initializer that your subclass also provides (either through inheritance or by overriding it).

As an example, the following BananaSplit class subclasses IceCreamSundae. It doesn’t declare any stored properties without default values. If that was all it did, it would have been eligible to inherit all of the initializers from IceCreamSundae. It elected, however, to override theinit(flavor:,topping:) designated initializer, as follows:

class BananaSplit: IceCreamSundae {
override init(flavor: String = "Vanilla, Chocolate, Strawberry",
topping: String = "Caramel syrup") {
super.init(flavor: flavor, topping: topping)
scoops = 3 // Bannana split always has three scoops
}
}

The following code creates a BananaSplit object:

let split = BananaSplit(flavor: "Vanilla, Pineapple, Cherry")

Because it implemented at least one initializer, it won’t inherit any other designated initializers. It does, however, automatically inherit the convenience initializer init(special:) because that convenience initializer relies on the designated init(flavor:,topping:) initializer and that one was implemented in this subclass. The following code demonstrates using the inherited convenience initializer to create a banana split:

let sundaySplit = BananaSplit(special: .Sunday)

Required Initializers

And just to make initializers even more interesting—that is to say, complicated—you can declare that an initializer is required using the required keyword, as follows:

required init(flavor: String, scoops: Int) { ...

A required initializer must be overridden and re-implemented by a subclass. The subclass has the choice of just overriding the initializer or declaring it as required again. If you simply override the initializer, subclasses of your subclass are not required to implement the initializer again. If you re-require the initializer (using the require keyword again), the subclass of your subclass is required to implement it as well.

The most commonly encountered required initializer is the deserialization initializer in the NSCoding protocol you used in Chapter 19. The init(coder: NSCoder) initializer should be re-implemented in each subclass so that each can properly reconstruct the object from an archive data stream. Your subclass must re-implement init(coder: NSCoder), and you should mark it as required so that any subclasses of your class must do the same.

Closures

A closure is an object that encapsulates both a block of code and the variables it needs to execute. Think of a closure as a self-contained bundle of functionality that you can pass around like any other value. The name comes from the way a closure “closes over” the variables it references when it is created. The following code fragment demonstrates the general form of a closure:

var externalValue = 2
let closure = { (parameter: Int) -> ReturnType in
return codeThatDoesSomething(parameter+externalValue)
}

A closure is written like a free-floating block of code within a set of curly braces. Here are the salient points:

· Like a function, a closure may have parameters. The caller supplies these values when the closure is executed.

· Closure parameters do not have external names, and they cannot declare a default value.

· A closure’s return type must be specified. Use -> Void for closures that don’t return a value.

· The closure’s parameters and return type are declared before the in keyword. The code of the closure follows the in keyword. A closure with no parameters is written () -> ReturnType.

· A closure may make use of its parameters, variables it declares in its code block, and variables that exist outside the code block. The latter are “closed over” when the closure is created.

· Closures are often referred to as code blocks, hearkening back to similar functionality in Objective-C. Many other languages refer to this kind of functionality as a lambda.

Normally, a variable ceases to exist once it is out of scope. For example, a function parameter exists only for the lifetime of the function. When the function ends, so do its parameter variables (along with any local variables it created). In the following code, the parameter number gets created when the function is called and disappears again when it returns:

func inScope(number: Int) {
// code that does something with number
}

In the following version of inScope(_:), the function returns a closure to its caller. The closure captures the number parameter when it is created.

func inScope(number: Int) -> ((Int) -> Int) {
return { (multiplier: Int) -> Int in
return number * multiplier
}
}

When the function returns, its number parameter would normally ceases to exist. But since it was “closed over” by the closure, it now also exists in the scope of the closure as well and will continue to exist for the lifetime of the closure.

After the function returns, its reference to the number parameter goes away. The parameter is now, effectively, a private variable in the closure—since there are no other references to it. Each time you call the function, a new parameter variable is created, and a new closure captures that variable, as shown here:

let times5 = inScope(5)
let times3 = inScope(3)

We can demonstrate this by executing the two closures. You execute a closure by treating the closure variable as if it were a function, as follows:

var result = times5(7) // returns 35 (5*7)
result = times3(7) // returns 21 (3*7)

The two closures each multiply the supplied parameter with the value they captured in the earlier call to inScope().

In another scenario, consider the case where the closure captures a variable and that variable still exists. A closure captures a reference to a variable, not its value. (The distinction between values and references is discussed a little later in this chapter.) All the code, inside and outside of the closure, refers to the same variable. To demonstrate that, let’s create a persistent variable and a closure that captures it.

var multiplier = 3
let sharedVariable = { (number: Int) -> Int in
return number * multiplier
}

When you execute the closure, it multiplies its parameter value with the value of the captured multiplier variable, as follows:

result = sharedVariable(4) // returns 12 (4 * multiplier)

If you then modify the multiplier variable, the closure will use the modified value, as follows:

multiplier = 5
result = sharedVariable(4) // returns 20 (4 * multiplier)

Capturing self

Swift is full of shortcuts that allow you write only the code needed to express your intent. There are, however, a couple of places where Swift requires you to spell out the obvious so that it’s, well, obvious. Closures are one of those places. Consider the following view controller, animating the appearance of a label:

class LabelViewController: UIViewController {
@IBOutlet var label: UILabel!

override func viewDidAppear(animated: Bool) {
UIView.animateWithDuration(1.5, animations: { label.alpha = 1.0 })
}
}

Look at the closure carefully and tell me what variable it is “closing over.” (Hint, the answer is not label.)

That’s right, the correct answer is self. Whenever you refer to a property or function within a method, you’re implicitly referring to the instance variable or instance function of the context object. Within the context of the viewDidAppear(_:) function, the expression storyboardreally means self.storyboard, and the function call setEditing(true, animated: false) is really self.setEditing(true, animated: false).

The distinction in closures can be important. The previous closure captured the self variable (the reference to the view controller object) and not a reference to the specific UILabel object. This is critical because, as you’ve seen, a closure keeps a reference to the variables it captures.

Let’s say I create this closure but then immediately replace the label property with a different UILabel object. When the closure executes, it will use the new UILabel object because it captured self, not the original UILabel object. And this is why Swift won’t let you write the preceding code. You must write the closure as follows:

override func viewDidAppear(animated: Bool) {
UIView.animateWithDuration(1.5, animations: { self.label.alpha = 1.0 })
}

Swift requires you to write self.label, self.storyboard, and self.setEditing(true, animated: false) when writing a closure. This makes it abundantly clear that you’re capturing self and not label or storyboard.

Using Closures

Using closures couldn’t be easier. When you create a closure, it becomes a value—one you assign to a variable or pass as an argument. Your use of closures will likely begin as arguments. iOS provides many opportunities to pass a block of code to methods that will ultimately execute that closure to accomplish your tasks. Take almost any project in this book, and you’ll see closures in action. In Chapter 16, the code that adapted the display when it was resized passed two closures to the transition coordinator, as follows:

coordinator.animateAlongsideTransition( { (context) in self.positionDialViews() },
completion: { (context) in self.attachDialBehaviors() })

The animateAlongsideTransition(_:,completion:) method takes two parameters, both closures. The first closure is executed to animate your views during the transition, and the second closure executes after the transition is complete.

Notice that the parameter in each closure doesn’t have a type. That’s because Swift has a lot of shortcuts that let you write concise closures.

Closure Shortcuts

Swift allows you to use a number of shortcuts that simplify your closures.

· If the parameter and return types of the closure are implied by the parameter or the variable you’re assigning it to, you can omit those types.

· You can omit the parameter names and use their shorthand names.

· If the code for a closure can be written as a single return statement, you can write just the return expression.

· If the closure is the last parameter to a function call, you can use the trailing closure syntax.

The first shortcut simplifies the parameters of the closure. In a situation like the animateAlongsideTransition(_:,completion:) method, the description of the closure has already been established by the method. If you look at the method declaration, you’ll see something like the following:

func animateAlongsideTransition(image
_ animation: ((UIViewControllerTransitionCoordinatorContext!) -> Void)!,image
# completion: ((UIViewControllerTransitionCoordinatorContext!) -> Void)!) -> Bool

This function describes two parameters. Both expect a closure that has one parameter (of type UIViewControllerTransitionCoordinatorContext) and returns nothing (-> Void). The closure you pass as an argument to the call must match that description. Because Swift already knows the number and types of the parameters and the type the closure will return, Swift will fill those details in for you. All you have to do is name the parameters, as follows:

{ (context) in self.positionDialViews() }

The type of the context parameter and the return type of the closure are both implied. In this situation, you can also save a few keystrokes by tossing the parentheses, as follows:

{ context in self.positionDialViews() }

If a parameter is uninteresting, you can replace its name with an _ (underscore), as follows:

{ _ in self.positionDialView() }

Shorthand Parameter Names

If you don’t want to name the parameters, you can use their shorthand names: $0, $1, $2, and so on. If you do that, you can leave out the entire parameters clause at the beginning of the closure. Take the customActionWithDuration(_:,actionBlock:) method of SKAction as an example. This function is defined as follows:

func customActionWithDuration(_ seconds: NSTimeInterval,image
actionBlock block: (SKNode!, CGFloat) -> Void)image
-> SKAction

The second parameter is a closure that receives two parameters (an SKNode and a CGFloat). When you call this function, you can write the closure as follows:

SKAction.customActionWithDuration( 3.0,
actionBlock: {
(node, elapsedTime) in
if elapsedTime > 0.5 {
node.alpha = elapsedTime/3.0
}
})

The closure for the actionBlock parameter tests the elapsedTime parameter. If more than half a second has elapsed, it sets the node’s alpha proportionally based on the elapsed time. You could write the same code this way:

SKAction.customActionWithDuration( 3.0,
actionBlock: { if $1 > 0.5 { $0.alpha = $1/3.0 } } )

In the second example, the entire parameter declaration is omitted. Swift assigns the first parameter the shorthand name of $0, the second one $1, and so on. Use these shorthand names exactly as you would the named parameters.

Tip Limit your use of shorthand names to contexts where the meaning and type of the parameters is obvious. The second example is much less obvious than the first.

Single Expression Closures

There’s an even shorter form for closures that return a value. If the code for the entire closure can be expressed in a single return statement, you can omit the return statement and write the closure as an expression. This is particularly useful with methods like Swift’s sort(_:) andmap(_:) array functions. Let’s create a simple to-do item array with the following code:

struct ToDoItem {
let priority: Int
let note: String
}
var toDoList = [ ToDoItem(priority: 3, note: "Recycle ice cream cups"),
ToDoItem(priority: 1, note: "Buy ice cream"),
ToDoItem(priority: 2, note: "Invite friends over") ]

You can sort this array with the array’s sort(_:) function. This function accepts a single closure used to compare any two elements in the array. The closure receives two parameters (the two array elements to compare) and returns a Boolean value indicating whether the first (left) parameter should be before the second (right) parameter in the new order. (You’ll find examples of this in the Learn iOS Development Projects image Ch 20 image Closures.playground file.)

Let’s sort the array into priority order. Writing this closure with named parameters would look something like the following:

toDoList.sort( { (left, right) in return left.priority < right.priority } )

As you learned earlier, you can also write the closure using the shorthand parameter names, as follows:

toDoList.sort( { return $0.priority < $1.priority } )

But since the entire closure is a single return statement, Swift lets you get away with leaving out the return and writing the closure as just the expression. The following two statements are equivalent to the previous two:

toDoList.sort( { (left, right) in left.priority < right.priority } )
toDoList.sort( { $0.priority < $1.priority } )

Trailing Closures

Closures can get even shorter—well, maybe not the closure, but the syntax used to pass a closure as a parameter. If the last argument of a function call is a closure parameter, you can omit that argument and write the closure immediately after the function call. This is called a trailing closure. The SKNode class has an enumerateChildNodesWithName(_:,usingBlock:) method. The following example shows how you would call that method passing the closure as a regular argument:

let scene = SKScene()
scene.enumerateChildNodesWithName("firefly", usingBlock: {
(node, _) in
node.hidden = false
})

To write the same code using a trailing closure, omit the last parameter and follow the function call with the closure, as follows:

scene.enumerateChildNodesWithName("firefly") { (node, _) in node.hidden = false }

Again, this is particularly useful with functions like sort(_:). Using the earlier single expression example, you can ultimately write the sort function as follows:

toDoList.sort() { $0.priority < $1.priority }

This last example combines type inference, shorthand parameter names, single expression, and the trailing closure shortcuts.

Closure Variables

When you’re ready to store a closure in a variable or write a function the takes a closure as a parameter, you’ll need to write a closure type. A closure type is the signature of the closure (the part before the in keyword) inside parentheses. You write a variable that stores a closure as follows:

var closure: ((Int, String) -> Int)

This variable stores a closure that receives two parameters, an Int and a String, and returns an Int. Closure parameters don’t have external names or default values, so only the parameter types are listed. You can later assign a closure to this variable and later execute it as follows:

closure = { (number,name) in return 1 }
closure(7,"deborah")

Similarly, a function with a closure parameter is written as follows:

func closureAsParameter(key: String, master: ((String) -> Int)) {
unlockDoor(master(key))
}

Since the closure is the last parameter, this function is eligible for tailing closure syntax, like this:

closureAsParameter("The Key") { (key) in return key.hash }

Protocols

A protocol is a set of properties or methods that a class (or other type) can adopt. A protocol is, effectively, a promise to implement a specific set of features. Once your class fulfills that promise, your class can be used in any place that wants a type with that protocol. A class that adopts a protocol is said to conform to that protocol.

You declare a protocol much the way you would a class, using the protocol keyword. As a simple example, let’s create a Flavor protocol as follows. These, and other, examples can be found in the Learn iOS Development Projects image Ch 20 image Protocols.playgroundfile.

protocol Flavor {
var flavor: String { get }
func tastesLike(flavor otherFlavor: Flavor) -> Bool
}

This protocol requires a String property named flavor and a function named tastesLike(flavor:) that returns a Bool.

Your class adopts protocols by listing them after the superclass name (if any), as follows:

class IceCream {
var flavor: String = "Vanilla"
var scoops: Int = 1
}

class Sundae: IceCream, Flavor {
func tastesLike(flavor otherFlavor: Flavor) -> Bool {
return flavor == otherFlavor.flavor
}
}

In this example, the class Sundae is a subclass of IceCream and adopts the Flavor protocol. Adopting the protocol requires that it have a flavor property and a tastesLike(flavor:) function. The first was already inherited from its superclass, so implementing the function is all that’s required to adopt this protocol.

Note Objective-C can define protocols with optional properties and methods. Your class can decline to implement an optional method and will still conform to the protocol. Swift protocols do not have optional members.

The adopting class can fulfill a property requirement with either a stored or a computed property that is implemented, overridden, or inherited. A protocol doesn’t care how a class implements the interface, just that it does. Every property in a protocol is followed by either { get } or { get set }. Any property will satisfy the former. If the protocol states the property is { get set }, you must implement a mutable property.

Once Sundae has adopted Flavor, it can be used anywhere there’s a variable of type Sundae, IceCream, or Flavor. This allows unrelated classes to be treated as a common type, as long as all adopt the same protocol. In the following example, the completely unrelated class Tofualso adopts the Flavor protocol:

class Tofu: Flavor {
var flavor: String = "Plain"
var weight: Double = 1.0

func tastesLike(flavor _: Flavor) -> Bool {
// Tofu doesn't taste like anything else
return false
}
}

You can now declare variables and parameters of type Flavor and interchangeably use Tofu and Sundae objects as follows:

var dessert: Flavor = Sundae()
var chicken: Flavor = Tofu()
if dessert.tastesLike(flavor: chicken) { ...

Protocols are regularly used for delegates. A class will use a protocol to define the delegate’s interface and then declare a delegate property that can store any object that adopts that protocol. Just look at almost any Cocoa Touch class that has a delegate property.

Extensions

An extension adds properties or methods to an existing class (or other type). You can add methods and computed properties to almost anything, even classes you didn’t write. Back in Chapter 7, I told you that adding an imageView property to the MyWhatsit class was poor MVC design because the MyWhatsit class is a data model and the imageView was really a view method. With extensions, you can save your design while still adding an imageView property to MyWhatsit. Start with (a simplified version of) the original class, as follows:

class MyWhatsit {
var name: String
var location: String
var image: UIImage?
...
}

In a separate source file, you can create an extension to MyWhatsit that adds the extra method, as follows. The extension keyword is used to show that you are extending the existing class (or other type), not defining a new one.

extension MyWhatsit {
var viewImage: UIImage {
return image ?? UIImage(named: "camera")!
}
}

Now when you create MyWhatsit objects, they’ll all have a viewImage property, just as if you had defined that property in the original class.

var thing = MyWhatsit(name: "Robby the Robot")
detailImageView.image = thing.viewImage

This preserves MVC separation because the code that manages the data model is separate from the code that deals with view object responsibilities, even though both belong to the same object. In another program, you might reuse the MyWhatsit class in the absence of the extension, in which case the same objects won’t have a viewImage property.

Extensions are also handy for adding new functions to common classes. If you need an inKlingon property added to the String type, you can do that in an extension. Then you can write "Hello".inKlingon and Swift will perform your translation, as follows:

extension String {
var inKlingon: String { return self == "Hello" ? "nuqneH" : "nuqjatlh?" }
}
...
let greeting = "Hello"
println(greeting.inKlingon)

There are a couple of restrictions to extensions.

· An extension cannot add stored properties to an existing type. You can only add methods and computed properties.

· You cannot override an existing property or method in an extension.

Structures

A structure, or struct, in Swift is very much like a class. Unlike most other languages, a Swift structure has more in common with a class than what it doesn’t. Here’s an example of a Swift structure:

struct SwiftStruct {
var storedProperty: String = "Remember me?"
let someFixedNumber = 9
var computedProperty: String {
get {
return storedProperty.lowercaseString
}
set {
storedProperty = newValue
}
}

static func globalMethod() {
}
func instanceMethod() {
}
init(what: String) {
storedProperty = what
}
}

In Swift, a structure shares the following traits with a class:

· Can define stored properties (and stored properties can have observers)

· Can define computed properties

· Can define methods (instance functions)

· Can define global functions

· Can have custom initializers

· Can adopt protocols

· Can be augmented with extensions

There’s very little about these traits that differ—in either capability or syntax—between classes and structures. There are differences, both significant and minor.

· A structure cannot inherit from another structure.

· A structure is a value type, not a reference type.

· A structure does not have a deinit function.

· A global function in a structure is declared using the static keyword instead of the class keyword.

The first is probably the biggest difference. Every structure is an isolated type. Structures do not form an inheritance hierarchy, they cannot participate in subtype polymorphism, and you cannot test their type (which would be pointless because they can only be one type).

Structures are value types. I explain the difference between value and reference types later. For now, just know that a structure is a collection of stored properties. When you assign it to a variable or pass it as a parameter, the entire structure is duplicated. Changes made to a copy do not affect the original.

Like a class, Swift automatically creates a default initializer if all of its stored properties have default values. Unlike a class, a structure also gets a memberwise initializer—assuming it doesn’t define any custom initializers of its own. A memberwise initializer is an init method whose parameters are the names of all of its stored properties. The following example defines a structure with two stored properties. The code that follows creates two instance of the structure using its automatically generated initializers:

struct StructWithDefaults {
var number: Int = 1
var name: String = "amber"
}

let struct1 = StructWithDefaults()
let struct2 = StructWithDefaults(number: 3, name: "john")

Tuples

Tuples are ad hoc, anonymous, structures. Tuples are a convenient way to group a few related values together and treat them as a single value. You write a tuple by surrounding a list of values with parentheses, like this:

var iceCreamOrder = ("Vanilla", 1)

This statement creates a tuple containing two values, a String and an Int, assigned to the single variable iceCreamOrder. The following example creates the same kind of tuple but also gives its members names:

let wantToGet = (flavor: "Chocolate", scoops: 4)

The type of a tuple is simply the types of its content. You can assign a tuple to any variable with the same type, as follows:

iceCreamOrder = wantToGet

Note There is no practical limit on how many, or what kinds, of values you can include in a tuple. A tuple can be made from floating-point numbers, strings, arrays, objects, structures, enums, dictionaries, closures, and even other tuples.

Tuples are extremely handy for returning multiple values from a function. You used this in Chapter 14 for the score() function; it returned both the player’s numeric score and a flag indicating whether the game had been won, in a tuple. In the following example, the nextOrder()function returns a (String,Int) tuple. Play around with these examples in the Learn iOS Development Projects image Ch 20 image Tuples.playground file.

func nextOrder() -> (flavor: String, scoops: Int) {
return ("Vanilla", 4)
}
...
let order = nextOrder()

You access the individual values within a tuple much as you would a structure or class. If the tuple members were given names, you can address them as properties, like this:

if order.scoops > 3 {
println("\(order.scoops) scoops of \(order.flavor) in a dish.")
} else {
println("\(order.flavor) cone")
}

If a member of a tuple is anonymous (that is, they don’t have member names like the ones in iceCreamOrder), you can still address the member using its index. A tuple member index is a number, starting at 0, assigned to each member value in the tuple. You use an index just like a property name, as follows:

if iceCreamOrder.0 == "Chocolate" {
println("\(iceCreamOrder.1) scoops of the good stuff.")
}

And there’s a third way of addressing the individual values of a tuple. When you assign the tuple, you can decompose the tuple into individual variables, as shown here:

let (what,howMany) = nextOrder()
if howMany > 3 {
println("\(howMany) scoops of \(what) in a dish.")
} else {
println("\(what) cone")
}

The first statement declares two new variables, what and howMany. Each is assigned to one value from the tuple. This is a convenient way to assign names to tuples with anonymous members or gain more direct access to each value. If you’re not interested in a particular value, replace its variable name with an _ (underscore), just as you would ignore a parameter, as in let (what,_) = nextOrder().

Enumerations

An enumeration, or enum, assigns symbolic names to a set of unique literal values. You write an enumeration as a list of the symbols you want to define, as follows:

enum Weekday {
case Sunday
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
case Saturday
}

This defines a new type, Weekday, that can be used much like any other type. The enumeration defines seven unique values. The following statement defines a new variable (dueDay) of type Weekday and assigns it the value Thursday:

var dueDay = Weekday.Thursday

When Swift already knows the type of the variable or parameter, you can leave out the enumeration type name, like this:

dueDay = .Friday

This is particularly handy when passing an enumeration value in an argument.

Raw Values

Swift’s internal representation of enumeration values is opaque—computer-speak for “you don’t know and you can’t find out.” All you need to know is the values are unique and can be assigned to a variable of that enumeration type.

Optionally, you can define a relationship between the values in an enumeration and values in another type. This alternate value is called the enumeration’s raw value.

In the following example, an enumeration is defined that has seven values. Each value can be converted to and from a corresponding Int value.

enum WeekdayNumber: Int {
case Sunday = 0
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
case Saturday
}

The choices for a raw value are integer, floating-point number, string, or character. If you choose an integer type, a unique number is automatically assigned to each enumeration value, as shown earlier. You can, optionally, assign specific values to particular cases, as shown with Sunday.

An enumeration value can be converted to its raw value using its rawValue property. Conversely, an enumeration value can be created from a raw value using its init(rawValue:) initializer, both shown here:

let dayNumber = WeekdayNumber.Wednesday.rawValue
let dayFromNumber = WeekdayNumber(rawValue: 3)

Note The conversion from a raw value to an enumeration can fail; all enumeration values have a unique raw value, but not all raw values have a corresponding enumeration value. See the “Optionals” section for more about failable initializers.

The dayNumber is an Int with a value of 3. This was obtained by converting the WeekdayNumber.Wednesday value into its raw value. The dayFromNumber is a WeekdayNumber variable containing the value Wednesday, obtained by converting the raw value of 3 into aWeekdayNumber.

Raw values can also be strings or characters. In the following example, an enumeration with string raw values is defined. For non-integer values, you must provide a raw value for every case, and there can be no duplicates.

enum WeekdayName: String {
case Sunday = "Sunday"
case Monday = "Monday"
case Tuesday = "Tuesday"
case Wednesday = "Wednesday"
case Thursday = "Thursday"
case Friday = "Friday"
case Saturday = "Saturday"
}

Just as with numeric raw values, you can convert to or from the enumeration value. The following code prints the message “Reports are due on Monday.”

let reportDay: WeekdayName = .Monday
println("Reports are due on \(reportDay.rawValue).")

Associated Values

Each enumeration value can also store a tuple of other values, called associated values. This lets you bundle other interesting values with a specific enumeration value. For example, an enumeration of failure reasons might have associated values with information about each particular kind of failure. A .DocumentNotFound value might include the name of the missing document, while the .SessionExpired value might have the time the session ended.

When you add associated values to an enumeration, extra storage space is set aside for the additional tuples. Each tuple is paired with a specific enumeration value. That tuple can only be used when the enumeration variable is set to that value.

It’s easier to explain with an example. In the following code, several of the WeekdayChild enumeration values have associated values:

enum Sadness {
case Sad
case ReallySad
case SuperSad
}

enum WeekdayChild {
case Sunday
case Monday
case Tuesday(sadness: Sadness)
case Wednesday
case Thursday(distanceRemaining: Double)
case Friday(friends: Int, charities: Int)
case Saturday(workHours: Float)
}

The .Tuesday and .Saturday values store an associated floating-point number. The .Friday value stores two additional integer values. And the .Thursday value goes completely meta, storing another enumeration value. The other cases do not have associated values; treat those like any other enumeration.

Enumerations and their associated values are constructed through initializers. What follows are some examples, which you can also find in the Learn iOS Development Projects image Ch 20 image Enumerations.playground file.

let graceful = WeekdayChild.Monday
let woeful = WeekdayChild.Tuesday(sadness: .ReallySad)
let traveler = WeekdayChild.Thursday(distanceRemaining: 100.0)
let social = WeekdayChild.Friday(friends: 23, charities: 4)
let worker = WeekdayChild.Saturday(workHours: 90.5)

Tip The external names for associated value tuple members are optional. You can leave them out and just use the values, as in WeekdayChild.Friday(23,4).

Oddly, you can’t access associated values directly. The only mechanism for retrieving them is through a switch statement, like this one:

var child = traveler
switch child {
case .Sunday, .Monday, .Wednesday:
break
case .Tuesday(let mood):
if mood == .ReallySad {
println("Tuesday's child is really sad.")
}
case .Thursday(let miles):
println("Thursday's child has \(miles) miles to go.")
case .Friday(let friendCount, let charityCount):
println("Friday's child has \(friendCount) friends.")
case .Saturday(let hours):
println("Saturday's child is working \(hours) hours this week.")
}

You obtain the associated values by decomposing the tuple using let statements within each switch case, as shown earlier. The reason for this odd mechanism is that an enumeration value could, potentially, contain any of the possible enumeration values. But the associated values are only valid when it is set to a specific enumeration value. The switch case ensures that access is only granted to the associated values for that specific enumeration value.

Extended Enumerations

Enumerations are full-blown types, like classes and structures. An enumeration can define computed properties and have static and instance methods. It can adopt protocols, can be extended by extensions, and can have custom initializers. You cannot add stored properties; use associated values for that. The following is an enumeration with computed properties, methods, and a special initializer:

enum WeekdayNumber: Int {
case Sunday = 0
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
case Saturday

var weekend: Bool { return self == .Sunday || self == .Saturday }
var weekday: Bool { return !weekend }
init(random: Bool) {
if random {
nextWeekDayNumber = Int(arc4random_uniform(7))
}
self = WeekdayNumber(rawValue: nextWeekDayNumber)!
nextWeekDayNumber++
if nextWeekDayNumber > WeekdayNumber.Saturday.rawValue {
nextWeekDayNumber = WeekdayNumber.Sunday.rawValue
}
}
func dayOfJulienDate(date: NSTimeInterval) -> WeekdayNumber {
return WeekdayNumber(rawValue: Int(date) % 7 + 2)!
}
}
var nextWeekDayNumber: Int = WeekdayNumber.Monday.rawValue

When writing code that runs in the context of an enumeration, the self variable represents its current value. You establish the enumeration’s value in the initializer by assigning a value to self. You’d use any of these features just as you would with a structure or object, as follows:

let today = WeekdayNumber(random: true)
if today.weekend {
clock.alarm.enabled = false
}

Numeric Values

Now you’re getting down to the simplest types, but there might still be a few surprises waiting for you. Swift has integer and floating-point numeric types. You’ve been using these throughout this book.

Integer types come in a variety of sizes and signs: Int, UInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, and UInt64. You’ll find examples of these in the Learn iOS Development Projects image Ch 20 image Numbers.playground file.

The vast majority of the time you should use Int, occasionally UInt, and almost nothing else. You’ll understand why shortly. The rest of the types are useful only when dealing with specific data sizes, such as binary message formats.

Floating-point numbers come in two flavors: Float and Double. Float is always 32 bits, and Double is always 64-bits.

When running a Swift program on a 32-bit processor, the Int and UInt types are 32 bits wide (equivalent to Int32 and UInt32). When compiled for a 64-bit processor, they are both 64 bits wide. The iOS Foundation library defines the CGFloat type. It is 32-bits (Float) when compiled for 32-bit processors and 64-bits (Double) on 64-bit processors. The Cocoa Touch framework makes extensive use of CGFloat.

Implicit Type Conversion

Swift, quite unlike most computer languages you’ve probably encountered, has no implicit type conversion. When you assign a variable, pass a value in an argument, or perform an operation on two values, the values you supply must exactly match the type expected (with only a few exceptions that I’ll get to in a moment). The following example demonstrates this:

var signed: Int = 1
var unsigned: UInt = 2
var double: Double = 3.0
var float: Float = 4.0
signed = unsigned // <-- invalid
unsigned = signed // <-- invalid
double = float // <-- invalid

One of the reasons Swift can infer types—relieving you from typing them over and over again—is because there’s never any ambiguity about what type a number or expression is, and there’s never any possibility of accidentally losing numeric precision through an assignment or conversion. It also means you must intentionally convert any values that aren’t the correct type.

This is the reason for my advice to use Int as much as possible. If all your integers are Int, you won’t have any conversions to do.

If you have one type and need another, you must explicitly create the type you need. You create integer and floating-point types exactly as you do objects, structures, and enumerations. The following code fixes the impedance mismatch shown earlier by creating new, compatible, types:

signed = Int(unsigned)
unsigned = UInt(signed)
double = Double(float)

The Int type has initializers that accept every other integer and floating-point type, and vice versa. Generally, these constructors will prevent loss of data by throwing an exception if the conversion cannot be completed. The following example results in an error because the integer value of 300 can’t be represented by an 8-bit integer:

let tooBigToFit = UInt8(300) // error

The exceptions are the integer initializers from floating-point values. These initializers will silently truncate the fractional portion of the value. The expression Int(2.6) will be the integer value 2.

Numeric Literals

Numeric literals, by contrast, are much more flexible. Swift recognizes a variety of number formats, as shown in Table 20-2.

Table 20-2. Literal Number Formats

Form

Description

123

Positive integer number

-86

Negative integer number

0xa113cafe

Hexadecimal number

0o557

Octal number

0b010110110

Binary number

1.5

Floating-point number

6.022e23

Floating-point number with exponent

0x2ff0.7p2

Hexadecimal floating-point number with exponent

Any numeric literal can include leading zeros and intermix underscores for readability. Neither changes the value. This lets you write 23_000_000_000 instead of 23000000000. If the type of the literal is not implied or specified, the first five formats in Table 20-2 result in an Int value. The remaining three will be a Double. In the following example, the variable is type Double because the literal defaults to type Double and you didn’t specify a type:

let avogadroNumber = 6.022_141_29e23

However, when you assign a literal to a variable or pass it as an argument, Swift will convert the literal to the receiving type as best it can. This is just about the only time Swift automatically converts types for you. In the following example, an integer literal is being assigned to a Doublevariable:

var double: Double = 3

The literal 3 is an integer. But since you’re assigning it to a floating-point variable Swift automatically converts the 3 into 3.0, as if you had written var double: Double = Double(3).

Numbers Are Types Too

Unexpectedly, even the simple numeric types are full-fledged types in Swift. A numeric type can have computed properties and methods and can be extended with extensions. The following extension adds a casualName property to the Int type:

extension Int {
var casualName: String {
switch self {
case 0:
return "no"
case 1:
return "just one"
case 2:
return "a couple"
case 3:
return "a few"
default:
return "many"
}
}
}

Now any Int value has a property that can be used like any other property. The following codes print the message “There are a few people here for ice cream.”

let headCount: Int = 3
println("There are \(headCount.casualName) people here for ice cream.")

The standard numeric types already have a number of useful properties. The min and max properties, for example, return the minimum and maximum value represented by that type. The expression Int.max will be the largest positive number you can store in an Int variable.

Overflow and Underflow

Swift has the usual suite of mathematical operations: addition (+), subtraction (-), multiplication (*), division (/), reminder division (%), increment (++, both prefix and postfix), and decrement (--, both prefix and postfix). There is also the standard set of reassignment operators: add to (+=), subtract from (-=), multiple with (*=), divide by (/=), and so on. Add to that the bit-shift operators (<< and >>), the bit-wise logical operations (&, |, and ^), and the Boolean logic operators (&& and ||). You should be familiar with all of these. If you have specific questions, refer to The Swift Programming Guide in iBooks.

Swift rigorously checks for overflown and underflow in all arithmetic operations. If you increment an integer and the result is too large to be represented by that type, Swift throws a program exception. In the following example, the result of multiplying these two numbers exceeds the value ofInt.max and terminates the program:

let big: Int = 999__999_999
let bigger: Int = 9_999_999_999
let wayTooBig = big * bigger // <-- overflow

If you have a reason to either embrace or ignore this situation, Swift provides a set of operators that ignore overflow and underflow: multiple ignoring overflow (&*), divide ignoring overflow (&/), remainder ignoring overflow (&%), add ignoring overflow (&+), subtract ignoring overflow (&-), and others.

Strings and Characters

Strings and characters are fundamental types in Swift. A String is swift is a value type. That means if you pass a string as a parameter you’re passing a copy of the string, not a reference to the original. Being a value type, a string can be a variable (mutable) or a constant (immutable), as follows:

var string: String = "Hello!"
let immutableString: String = "Salut!"

String and Character Literals

A string literal is written between double quotes. String literals recognize several escape sequences, all starting with a single \ (backslash) character. Table 20-3 shows the escape codes you can include in a string.

Table 20-3. String Literal Escape Codes

Escape Sequence

Character in String

\\

A single \ character

\"

A single ” character

\'

A single ’ character

\t

Horizontal tab character

\r

Carriage return character

\0

Null character

\u{nnnn}

Unicode scalar with the hexadecimal code of nnnn

\(expression)

String representation of expression (string interpolation)

Swift uses the same syntax for character literals. The default type of a string literal is the String type. But like numeric literals, Swift will convert a single character string literal into a character literal when it is assigned to a Character type or you explicitly create a Character value. The following examples demonstrate this:

let thisIsAString = "String"
let thisIsAlsoAString = "c"
let thisIsACharacter = Character("c")
let thisIsAlsoACharacter: Character = "c"

A string literal with a single character is converted to a Character type when it’s expected to be a Character. Otherwise, it will act like a String.

If you need to create an empty String, use an empty string literal ("") or create an empty String value (String()).

Unicode

Swift fully embraces the Unicode character set. All Swift strings are encoded using Unicode. Furthermore, Swift source files accept Unicode encoding, so you can include any Unicode character right in your program’s source file. The following string literal is a perfect example:

let hungary = "Üdvözlöm!"

Unicode characters are also acceptable in the Swift language. Variable, class, method, parameter, and property names can all include Unicode characters. Basically, any character that is not part of the Swift language is valid in a symbol name. The following two variable names are legal in Swift and can be used anywhere a more pedestrian variable name is used. (See the Learn iOS Development Projects image Ch 20 image Strings.playground file for examples of variable names using Emoji characters.)

let olá = "Hello!"
let π = 3.14159265359
return π * (r*r)

Tip Swift strings are delimited by the ASCII double quote character (", Unicode 0x22). The more typographical “curly quotes,” like the ones around the words “curly quotes,” are not recognized as string delimiters. That means you can include single and double curly quotes in your strings without escaping them, like this: "Rose said “Let’s Go!”".

Unicode encoding is normally transparent, but it can occasionally have odd side effects. Swift uses a particular style of encoding that require some Unicode characters be represented by two or more values. Some string methods will deal with the individual values in your string, while others will interpret the characters in your string. In the following example, the tricky value contains a single Unicode character, composed from two Unicode scalars:

let tricky = "\u{E9}\u{20DD}" // é

If you ask this string what its length is, it will return 2. If you ask it how many characters it has, it will return 1. Refer to the sections in The Swift Programming Guide on Unicode character encoding and conversion for the details.

String Interpolation

String interpolation is just a fancy name for embedding expressions in a string literal. The expression is converted into a string and becomes part of the resulting string. You’ve seen this several times in earlier chapters. In the following example, the aboutPi variable is set to “The value of π is approximately 3.14159265359.”

let aboutPi = "The value of π is approximately \(π)"
let truth = "The character count of \"\(tricky)\" is \(countElements(tricky))"

The π variable created earlier was interpreted and converted into a string, which then replaced the \(expression) in the string literal. The expression can be anything (formulas, objects, function calls) that Swift can convert into a string.

Tip To have objects of your custom class convert themselves into strings, override the description property.

While extremely convenient, what string interpolation doesn’t provide is any formatting control. Expressions are converted to strings as Swift sees best; you can take it or leave it. If you need to control how values are formatted, say you want an integer value converted into hexadecimal, turn to the NSString class. The following example uses the NSString(format:) initializer to create a string with precise formatting:

let aboutPi: String = NSString(format: "The value of %C is about %.4f", 0x03c0, π)

The format specifiers, which begin with % (percent sign), can perform a wide variety of conversion, and you have a lot of control over their format. The %f conversion, for example, can limit the number of significant digits after the radix point. In this case, it was capped at four digits. The number 0x03c0 could have been converted into a decimal or octal number but was instead converted to its Unicode character using %C. The resulting NSString is then assigned to the aboutPi variable, which brings us to the next topic.

Strings Are NSStrings

Swift String values are interchangeable with Objective-C NSString objects. You can use a String value wherever an NSString object reference is needed, and vice versa. In the previous section, an NSString object was created and then assigned to the aboutPi: Stringvariable. You can use it like any String and then turn around and pass it to any parameter that expects an NSString.

Swift, however, still treats String values and NSString objects as separate types. If you’ve created a String value, Swift assumes it only has the methods and properties of a String. If you have an NSString variable, Swift assumes it only has the methods and properties of theNSString class—even though it actually has both. To use NSString methods on a String value, simply cast from one to the other, as shown here:

let sparkRange = (string as NSString).rangeOfString("spark")
let objcString = string as NSString
let words = objcString.componentsSeparatedByString(" ")

In the first statement, the String value is temporary cast to the NSString type and used to call the rangeOfString(_:) function. In the second statement, the string is again converted to an NSString object but is then assigned to a variable. Since the type of the variable isNSString, you don’t have to cast it to use any of the NSString properties or methods. You can also do the reverse, casting any NSString object into a String value.

Note A String, even if it’s mutable, cannot be cast to an NSMutableString object.

NSString is a big class and has many useful functions. The String type, by contrast, has very few. By casting your String to NSString, you immediately gain access to the huge repertoire of NSString features. See the NSString class documentation to discover what it offers.

String Concatenation

One feature the String value does offer is string and character concatenation. The + operator will create a new string by concatenating two other strings, as follows:

let message = "Amber says " + hungary

You can add a string to the end of a mutable string using the += operator. You can also append either a string or an individual character using the append(_:) function, both shown here:

var mutableString = "¡Hola!"
mutableString += " James"
let exclamation: Character = "!"
mutableString.append(exclamation)

When this code finishes, the mutableString variable contains “¡Hola! James!”

Attributed Strings

You’ve seen, throughout this book, a number of UIView classes and drawing methods that use attributed strings, instead of regular strings. An attributed string associates attribute values with a range of characters within the string. Attributes can express the font the characters are drawn in (font family, size, style), color, typographical adjustments (character spacing), alignment (right justified, superscript, subscript), text decorations (underline, strikethrough), and so on. Attributed strings are flexible and can describe a broad range of complex typography. In concept they’re not complicated, although they can be a little tedious in practice.

Attributes are expressed as a dictionary of values. The key identifies the kind of attribute. This dictionary is then associated with a range of characters. The following examples, which you can find in the Learn iOS Development Projects image Ch 20 image AttributedStringproject, show how attributed strings are constructed:

let fancyString = NSMutableAttributedString(string: "iOS ")
let iOSAttrs = [ NSFontAttributeName: UIFont.italicSystemFontOfSize(80),
NSForegroundColorAttributeName: UIColor.redColor(),
NSKernAttributeName: NSNumber(integer: 4) ]
fancyString.setAttributes(iOSAttrs, range: NSRange(location: 0, length: 3))

This first block of code creates a mutable attributed string from a plain string. It then creates a dictionary, defining three attributes: the italic system font at 80 points, the color red, and a kerning (inter-character spacing) of 4 points. Those attributes are applied to the first three characters of the string. Note that the space character (fourth character in the string) has no attributes.

This technique used the NSMutableAttributedString class. Use this class when you want to assemble your attributed string piecemeal or you want to assign different attributes to particular ranges within the string. The next example uses a much simpler technique:

let shadow = NSShadow()
shadow.shadowOffset = CGSize(width: 5, height: 5)
shadow.shadowBlurRadius = 3.5

let appAttrs = [ NSFontAttributeName: UIFont.boldSystemFontOfSize(78),
NSShadowAttributeName: shadow ]
let secondString = NSAttributedString(string: "App!", attributes: appAttrs)

The second technique creates an attributed string directly from a string and a dictionary of attributes. The appAttrs dictionary describes the system bold font at 78 points. It also applies a drop shadow, defined with an offset of (5.0,5.0) and blur radius of 3.5. When you create an attributed string this way, the attributes apply to all of the characters and the object is immutable.

fancyString.appendAttributedString(secondString)
label.attributedText = fancyString

Finally, the second attributed string is appended to the first. The appended string retains all of its attributes. The fancyString object now has eight characters, with one set of attributes for the first three, a different set for the last four, and still no attributes for the space between. All attributes have default values, and each character will use the default values for any attributes it’s missing.

When the attributed string is assigned to a UILabel, as shown in Figure 20-2, its attributes determine how it is drawn.

image

Figure 20-2. An attributed string in a label

Here are some tips for using attributed strings:

· An attributed string is not a subclass of String or NSString. It has an NSString (its string property), but it isn’t an NSString and you can’t use it place of a String or NSString.

· If the attributes apply to the entire string, you can create a homogenous, immutable, attributed string using NSAttributedString(string:,attributes:).

· If you want to create an attributed string with a mixture of different attributes, you must create an NSMutableAttributedString and construct it piecemeal.

· Using a mutable attributed string, you can set the attributes for a range of characters (setAttributes(_:,range:)), which replace any previous attributes for that range. You can also add (addAttributes(_:,range:)) or remove (removeAttributes(_:,range:)) attributes. These methods combine with, or selectively remove from, the existing attributes.

Caution Never change an attribute by altering the value object in an attribute dictionary that’s already been assigned to a range. You must always replace the attributes to change them.

Find the NSAttributedString UIKit Additions Reference in Xcode’s Documentation and API Reference window. The “Constants” section lists all of the attribute keys supported by iOS and what kind of value object to supply for each.

Collections

Swift has two native collection types: arrays and dictionaries. An array is an ordered collection of values. You address individual elements by numeric index. A dictionary maps keys to values. You address each element using its key. Dictionaries are sometimes called associative arrays.

You’ve been using arrays and dictionaries throughout this book. I won’t bore you with the details (although many can be found in The Swift Programming Guide), but here are some things you should know.

First, all Swift arrays and dictionaries have a type; they are not universal collection objects. An array of [Int] type can store only Int values. For a dictionary, you specify both the type of the key and the type of the value. The preferred method of declaring an array type is with the syntax[Type]. For dictionaries, it’s [Type:Type], where the first is the key’s type, and the second is the value’s. The following examples show some array variables being declared:

var emptyArrayOfInts: [Int] = []
var anotherEmptyArrayOfInts = [Int]()
var arrayTypeInferredFromElements = [ 1, 2, 3 ]
var arrayWithADozenPis = [Double](count: 12, repeatedValue: 3.1415926)

The emptyArrayOfInts is explicitly declared to be an array of Int values. Its default value is an empty array. The anotherEmptyArrayOfInts variable has the same type, inferred from the type of its default value. This is the syntax you use to create an empty array of a specific type. The arrayTypeInferredFromElements is also an array of Int values. Swift determined its type by looking at the types of the values in the literal array.

Finally, the arrayWithADozenPis variable uses a special array initializer that generates an array of arbitrary size and fills each element with the same value. Now here are some examples with dictionaries:

var emptyDictionary = [String:String]()
var dictionaryTypesInferredFromElements = ["red": UIColor.redColor() ]

The emptyDictionary contains an empty dictionary that maps String keys to String values. The dictionaryTypesInferredFromElements variable has String keys and UIColor values, inferred from the default value.

The syntax for a literal array is [ element, element ]. A literal array can contain any number (even zero) elements, separated by commas. A literal dictionary is written [ key: value, key: value ]. If you’re assigning a collection to a variable or parameter, all of the elements, keys, and values must be compatible with the type of the array or dictionary.

Like String values, arrays are interchangeable with NSArray objects, and dictionaries are interchangeable with NSDictionary objects. Also like String values, arrays and dictionaries are value types. When you pass an array or dictionary as an argument, the entire collection is copied.

Note Arrays and dictionaries aren’t actually copied when you pass them as a parameter. Swift uses a technique of “lazy copying” that waits until the called function actually tries to modify the collection before duplicating it. Since most functions do not change the collections passed to them, Swift avoids the overhead of repeatedly copying the collection while maintaining the illusion that they are always copied.

Here’s the crash course on accessing and modifying an array:

· Get the value of an element using subscript syntax: array[1]

· Replace an element by assigning it, using subscribe syntax: array[1] = value

· Append an element to the end of the array with the append(_:) function: array.append(value)

· Append another array to the end of the array using the concatenation assignment (+=) operator: array += [ value, value ]

· Insert an element at an arbitrary position using the insert(_:,atIndex:) function: array.insert(value, atIndex: 3)

· Remove an element with the removeAtIndex(_:) function: array.removeAtIndex(2)

· Get the number of elements in the array from the count property: array.count

· See whether the array is empty from its isEmpty property: array.isEmpty

Using a dictionary is similar but instead of an index you address each element using its key.

· Get a value using subscript syntax and a key: dictionary["key"]

· Add or replace a value by assignment, using subscript syntax and a key: dictionary["key"] = value

· Add or replace a value, and also determine the value being replaced, using the updateValue(_:,forKey:) function: let previousValue = dictionary.updateValue(value,"key")

· Remove a value by setting it to nil, using subscript syntax: dictionary["key"] = nil

· Remove a value and discover the value being removed using the removeValueForKey(_:) function: let removedValue = dictionary.removeValueForKey("key")

Keys in a dictionary are unique. Setting a value for an existing key replaces the value previous stored for that key. The keys to a dictionary are often strings but can be any type that conforms to the Hashable protocol. Swift’s String, Int, Double, and Bool types are all suitable keys. A type that conforms to Hashable must provide the following:

· It implements its == operator so it can be compared with other values of the same type.

· It efficiently implements a hashValue property.

Another thing you’re going to want to do is iterate through the values in an array, a dictionary, or even a string for that matter. To do that, you need to know a little about for loops.

Control Statements

Swift, like all C-like languages, has the usual complement of control statements: if, if-else, else-if, for, while, do-while, and switch. The if, if-else, else-if, while, and do-while don’t hold any surprises, but there are a couple if cosmetic differences between Swift and similar languages.

· The condition expression does not have to be enclosed in parentheses.

· The condition must be a Boolean expression.

· The curly braces for the conditional code block are required.

Here are a few trivial examples. You’ll find these in the Learn iOS Development Projects image Ch 20 image Control.playground file.

var condition = true
var otherCondition = true

if condition {
// condition is true
}

if condition {
// condition is true
} else {
// condition is false
}

if condition {
// condition is true
} else if otherCondition {
// condition is false and otherCondition is true
} else {
// Both condition and otherCondition are false
}

while condition {
// Repeat while condition is true
condition = done
}

do {
// Execute once
otherCondition = done
// Repeat until otherCondition is false
} while otherCondition

Swifts for and switch statements, on the other hand, have many talents. Let’s take a look at for loops first.

for Loop

Swift’s for loop comes in three flavors: traditional, range, and collection. The traditional version is the composed init/while/increment form you see in all C-like languages. Here’s an example:

for condition = true; condition; condition = false {
}

The first statement is executed once to initialize the loop. Then, as long as the condition expression is true, the loop repeats. At the end of each loop, the increment statement is executed, and the condition expression is reevaluated. No surprises here.

The other two forms, often referred to as for-in statements, iterate over a range of numeric values or the elements in a collection. The range form looks like the following:

for i in 0..<100 {
// perform 100 times, with i=0 through i=99
}

for i in 0...100 {
// perform 101 times, with i=0 through i=100
}

The for-in range loops over a sequence of numbers, described by the range. The closed-range, 0...100, includes all of the value from 0 to 100, inclusive (101 numbers in total). The half-open range, 0..<100, includes the number from 0 to one less than 100. Note that either value in a range can be any numeric expression, such as 0..<inventory.count.

Caution The start value of a range must be less than or equal to the end value.

The second for-in loop format iterates over contents of a collection. This can be used to loop through the values in an array, dictionary, or string. For arrays and strings (which, in this situation, is treated as an array of characters) the format is simple, as follows:

let notes = [ "do", "re", "mi", "fa", "sol", "la", "ti" ]
for note in notes {
// Loop executes 7 times: note is "do" first time, "re" second time, ...
}
for character in "When you know the notes to sing, you can sing most anything" {
// Loop executes 59 times, once for each character in the string
}

When used with a dictionary, the loop variable is a tuple containing the (key,value) pair of each entry. You can use a tuple loop variable or decompose it into key and value variables. Both are shown in the following example:

let doReMi = [ "doe": "a deer, a female deer",
"ray": "a drop of golden sun",
"me": "a name, I call myself",
"far": "a long long way to run",
"sew": "a needle pulling thread",
"la": "a note to follow so",
"tea": "I drink with jam and bread" ]
for note in doReMi {
// tuple loop variable
println("\(note.0): \(note.1)")
}

for (noteName,meaning) in doReMi {
// decomposed variables
println("\(noteName): \(meaning)")
}

Note that you never put a let, var, or a type for the loop variable. It is always a constant (let), and its type is dictated by the range or the collection’s element type. Also remember that arrays and strings are always processed in sequential order, but dictionaries are unordered collections, and the order of elements is indeterminate.

switch Statement

Swift’s switch statement is a Swiss Army knife of useful tools, far exceeding the capabilities of switch statements you’ll find in similar languages. Let’s begin with a simple example, which you’re undoubtedly familiar with.

let number = 9
switch number {
case 1:
println("The lonest number")
case 2:
println("Enough to tango")
case 3, 5, 7:
println("\(number) is prime")
case 4, 6, 8:
println("\(number) is even")
case 13:
println("Considered unlucky")
default:
println("\(number) is a not number I'm familiar with")
}

There are a number of features you should be aware of.

· You can switch on most Swift types (integer, string, enumeration, tuple, and any object or struct that conforms to the Equatable protocol).

· Multiple matching conditions can be listed in a single case statement, separated by commas.

· There is no “fall through.” Execution of the statement finishes at the end of each case code block. If you want one block to fall through to the next, end the block with the special fallthrough statement.

· Because there is no “fall through,” break statements are not required, but you can still use them to exit a block early. If you have a case that has no code, use a single break statement; each case must have a code block, and a break satisfies that requirement.

· All switch statements must be exhaustive, which means they have to cover every possible case. For enumerations, this means you must provide a case for every enumeration value. If your cases aren’t exhaustive (or Swift is unable to determine that they are), you must include a default case.

What makes the switch statement so powerful are its case expressions. A case expression is actually a pattern matching mechanism. It can be a constant (as shown earlier), a range, an arbitrary expression, or a tuple containing multiple patterns. You can bind tuple values to new variables or qualify the case expression with arbitrary Boolean conditions. Let’s look at these variations, one at a time.

Range Cases

A case can also be a range, as shown in the following example:

let testScore = 91
switch testScore {
case 94...100:
println("Outstanding!")
case 86...93:
println("Very respectable")
case 75...85:
println("Pretty good")
case 60...74:
println("OK")
default:
println("Fail")
}

The integer value testScore is evaluated against each closed range. “Can the ranges overlap?” you ask. “Can they include variables or expressions?” you ask. Yes, they can. Check out the following switch statement:

let passingScore = 55
switch testScore {
case 94...100:
println("Outstanding!")
case (100+passingScore)/2...100:
println("Very respectable")
case passingScore...100:
println("Good enough")
default:
println("Fail")
}

Some of these ranges are determined by variables, and some include expressions. The ranges also overlap. This case statement works because of these rules:

· Cases are evaluated in order.

· The first case to match the value is executed.

If you have two overlapping cases, order them so the one with precedence is earlier in the case list.

Switching Tuples

Now take a look at switching on a tuple, as shown in the following example:

var sandwich = ("pastrami", "swiss")
var name = ""
switch sandwich {
case ("tuna", "cheddar"):
name = "Tuna melt"
case ("ground beef", "cheddar"):
name = "Cheeseburger"
case ("ground beef", _):
name = "Hamburger"
case ("steak", "cheddar"):
name = "Cheesesteak"
case ("ham", "american"):
name = "Ham & Cheese"
case ("ham", "gruyère"):
name = "Croque-monsieur"
case ("ham", "swiss"):
name = "Cuban"
default:
name = "\(sandwich.0) with \(sandwich.1)"
}

The patterns in each case are applied to the corresponding value in the switch tuple. If all match, the case is executed. In this example, most of the patterns are constants. But any of them could be a variable, an expression, or a range, just like a nontuple switch statement.

You can also have a wildcard that always matches a value in the tuple. If you want to ignore that value, replace the tuple pattern with _ (underscore), as shown in the ("ground beef", _) case in the previous example. If you want to match all values and also inspect that value in your code, bind the value using a let statement, as shown in the following example:

sandwich = ("ground beef", "blue cheese")
switch sandwich {
case ("tuna", "cheddar"):
name = "Tuna melt"
case ("ground beef", let cheese):
name = "Hamburger with \(cheese)"
default:
name = "Today's Speical"
}

The let cheese pattern matches every possible value of sandwich.1 and then binds that value to the cheese variable. You can now use cheese and sandwich.1 interchangeably in that case’s code.

Back in the “Enumerations” section, a switch statement was also used to access the associated values of an enumeration. With your fresh infusion of switch statement knowledge, you might want to look at that example again.

And if that weren’t enough flexibility, you can qualify any case with an arbitrary condition—like tacking on an additional if statement. You can follow a case statement with a where expression. If the case pattern matches, the where condition is then evaluated. If it’s true, then the caseblock is executed. If not, the case didn’t match and the next case is considered. The following example demonstrates this:

let now = NSDate()
let cal = NSCalendar.currentCalendar()
let when = cal.components(.HourCalendarUnit | .WeekdayCalendarUnit, fromDate: now)
var special = ""
switch when.weekday {
case 1, 7 where when.hour<13: // weekend (Sunday or Saturday) before 1 PM
special = "Eggs Benedict"
case 1, 7: // weekend, the rest of the day
special = "Cobb Salad"
case 2 where when.hour<8: // Monday, before 8 AM
special = "Ham with Red-eye Gravy"
case 3, 5 where when.hour<10: // Tuesday or Thursday, before 10 AM
special = "Fried Egg Sandwich"
case 4: // Wednesday, all day
special = "Ruben"
case 5, 6: // Thursday (after 10 AM) or anytime Friday
special = "Egg Salad Sandwich"
default: // any other time
special = "Cheeseburger"
}

The when variable contains calendar components for the current date and time. Calendar components are understandable time units, like the day of the week, the name of the month, and so on. This case statement uses a combination of patterns to match the weekday, combined with a Boolean expression to qualify the time of day. The expressions could be anything and might also consider if it was a holiday or Friday the 13th.

Optionals

For more than a half-century, programmers have been struggling with a problem: when is a value not a value? There are often situations where a variable, like a date, might contain a valid date object and sometimes it wouldn’t. Long ago, programmers settled on the convention of storing a zero for the pointer or object reference value to indicate that it doesn’t refer to a valid object. They called this value NULL or nil.

Note This practice became so widespread that modern computer memory hardware is now designed so there is never any valid memory at, or near, address 0x00000000. This prevents an empty pointer reference from being confused with valid data. (It’s also a quick way to crash your program.)

Early programming languages will allow any pointer or object reference can be set to nil. That means that any object reference, in any variable and parameter, in any function could be nil. You either have to test every single incoming value for nil or just hope the caller never sends you anil reference when you don’t expect one. This dilemma is unquestioningly the single most common cause of program crashes on iOS and most other platforms.

The situation gets worse with values like integers. You must reserve one value to mean that the number is not valid. Sometimes this can be as simple as 0 or -1, but if those too are useful numbers, you might have to pick a number like -999 or 9,223,372,036,854,775,807. And there’s no convention for this, so if someday -999 turns out to be a usable number, all that code has to change. And it gets worse with smaller types. Consider a Boolean value. Do you pick true or false to mean that it’s neither true nor false?

Swift solves this, and a host of other problems, with the optional. An optional type is a type that can either hold a value or have no value at all. Every Swift type has an optional type, designated by a question mark (?) following the type name. An Int type always stores an integer value. AnInt? type can store any integer value or might have no value at all.

The optional type lets programmers do what they’ve always needed to do; declare a variable that might have a value or might not. But Swift does it in a very clear and deliberate way and without reserving any values.

More importantly, when you don’t use an optional, Swift guarantees that the variable will contain a valid value. Always. No question. If you have an NSDate parameter, that parameter will always have a valid date object in it. You never have to test to see whether it’s nil, and your program can never crash because you forget to test for nil.

Using Optionals

You declare an optional by suffixing any type with a ?, as shown in the following examples:

var sometimesAnObject: NSDate? = NSDate()
var sometimesAString: String? = nil
var sometimesAnInt: Int?
var sometimesAnAnswer: Bool?

In the first example, sometimesAnObject can store either an NSDate object or the special value nil. In Swift, nil does not mean zero; it is a special value reserved to mean “no value” and does not equate to any other value. The sometimesAString variable stores an optional string, preset to “no value.” When you declare an optional, you don’t have to supply a default value; Swift automatically sets it to nil. Both sometimesAnInt and sometimeAnAnswer are pre-initialized to nil.

You can use the “old school” method and test an optional for nil, just as you might test a pointer for NULL in another language. In the following example, the sometimesAnObject is compared to nil and then used accordingly:

if sometimesAnObject != nil {
println("The date is \(sometimesAnObject!)")
} else {
println("I better not use sometimesAnObject")
}

You determine whether an optional has a value by comparing it to nil (either with optional == nil or with optional != nil). In fact, that’s the only thing you can do directly with an optional. Once you determine that the variable has a value, you access its value with theoptional! syntax. The exclamation point unwraps the optional, accessing its underlying value.

And here lies the danger. If you unwrap an optional that doesn’t have a value, you can crash your program just as fast as using a NULL pointer in C. To help you avoid the mistakes of the past, Swift provides a special if statement just for dealing with optionals. The following code is equivalent to the previous example:

if let date = sometimesAnObject {
println("The date is \(date)")
} else {
// This block has no 'date' variable
}

The if let variable = optional statement is called optional binding, and it does three things in a single step. It first checks to see whether sometimeAnObject contains a value (sometimesAnObject!=nil). If it does, it creates a new constant (let date: NSDate) and then unwraps the optional and assigns it to that constant (= sometimesAnObject!). The code block of the if statement then executes. Since the constant (date) is not an optional, you can freely use it in the body of the block—no unwrapping required.

If sometimesAnObject does not contain a value, nothing happens. The if block doesn’t execute. If there was an else block, it executes instead, but there’s no date value defined there.

You might be imagining that your code will now be filled with if optional != nil and if let value = optional statements. Don’t worry. Swift has a shortcut that simplifies testing for nil in many circumstances, which I’ll get to in a moment.

Optionals Carry

An optional is a type, distinct from any other type. When you let Swift choose the type of a variable, you may end up with an optional where you might not expect one. The following is a simple example:

var dictionary = [String:String]()
let key = "key"
let value = dictionary[key] // value: String?
if let existingValue = value {
println("The value for key \"\(key)\" is \(existingValue).")
} else {
println("There is no value for key \"\(key)\".")
}

The variable value is of type String?. “Why?” you ask. Because the return type of the dictionary subscript accessor is an optional. The dictionary might not have a value associated with that particular key. So, the return type is an optional that can also return “no value” for the answer.

The side effect is that you’ve created an optional variable (value), and if you want to use the result you must consider the possibility that there is no value for the key "key".

Optional Chaining

The obvious reason for testing to see whether an optional has a value is to avoid accessing the value that’s not there or the properties that don’t exist, or calling any of the functions that won’t work. Swift has an optional chaining syntax that tests a variable and performs the next part of the expression (property access, function call, and so on) only if it contains a value. If it doesn’t, the expression does nothing. Here’s an example:

class Cat {
var quote: String { return "Most everyone's mad here." }
var directions: String?
var friend: Hatter?
func disappear() { println("I'm not all here myself.") }
}
var cheshire: Cat?

cheshire?.disappear()

The cheshire variable contains an optional Cat? object. The statement cheshire?.disappear() uses optional chaining. The ? after the cheshire variable says “Check to see if cheshire contains a value and perform the rest of the expression only if it does.” That simple statement is roughly equivalent to the following code:

if cheshire != nil {
cheshire!.disappear()
}

Optional chaining can also be used to safely set a property, as follows:

cheshire?.directions = "Return to the Tulgey woods."

When used with properties or the return values of methods, optional chaining will turn any property or return value into an optional. In the following example, the words variable becomes an optional:

let words = cheshire?.quote

The words constant is a String?. The quote property is not optional, but since it was optionally invoked by chaining, the expression becomes an optional. When cheshire? is evaluated, Swift checks to see whether it is nil. If it is nil, Swift stops evaluating the expression and immediately returns nil. So, even if quote can never return a nil value, cheshire?.quote can. In the next example, optional chaining is compounded with an optional property:

let whereToGo = cheshire?.directions

The whereToGo variable is still a String?. The directions property is also an optional, but there are no “optional optionals” in Swift. This expression will return either nil or a String. If it returns nil, there’s no way (unless you go check) to know whether it was becausecheshire was nil or directions was nil. Optional chaining can be as deep as you like, as the following example shows:

class Mouse {
func recitePoem() { }
}
class Hatter {
var doorMouse: Mouse?
func changePlaces() { }
}

cheshire?.friend?.doorMouse?.recitePoem()

The last statement will call the Mouse object’s recitePoem() function only if cheshire, its friend property, and that property’s doorMouse property, all have values. If any don’t, the statement does nothing.

It’s not obvious, but optional chaining turns any statement into an optional. You probably don’t think of the recitePoem() function as returning a value, but to Swift it does, and you can use this to your advantage.

This gets a little esoteric, but in Swift the Void type is still a type, and it returns a value, the empty tuple (()), a value with no values. So, while the recitePoem() function doesn’t return anything useful, when it becomes an optional, you can test to see whether it returns nothing or nil. (I told you this gets esoteric.) The following example demonstrates this:

if cheshire?.friend?.doorMouse?.recitePoem() != nil {
// cheshire has a friend with a doormouse that recited a poem
}

If all of the variables and properties contain a value, the recitePoem() function executes and returns the void tuple (()). If any were nil, the expression stops and results in nil. You can test to see whether you got back a void result or nil, which tells you whether the function executed. See, that wasn’t so complicated after all.

Failable Initializers

Initializers can also be optional. These are called failable initializers. A failable initializer may decide that it can’t create the specific object, structure, enumerator, or whatever you’re trying to conjure up. It aborts the construction of the new type and returns nil. You’ve used failable initializers in earlier chapters. In MyStuff app, you created a UIImage from a resource in your project using code similar to the following:

let noSuchImage = UIImage(named: "SevenImpossibleImages")

It’s entirely possible that a resource named SevenImpossibleImages isn’t in your app’s bundle. The UIImage can’t be constructed, and the noSuchImage optional is set to nil.

You can write your own failable initializer using the init? function name. The following example shows a class that represents a point of interest on a map. It has a database of known locations and their coordinates. If the point of interest isn’t known, the object can’t be created.

class PointOfInterest {
let name: String
let location = CLLocationCoordinate2D(latitude: 0, longitude: 0)

init?(placeName name: String) {
self.name = name
if let loc = locationForPointOfInterest(name) {
self.location = loc
} else {
return nil
}
}
}

let castle = PointOfInterest(placeName: "Mystery Castle")

The initializer function decides whether the object can be created. If not, it deliberately returns nil, signaling that the initializer failed. This makes the return type of the initializer PointOfInterest?.

Implicit Unwrapping

I’ve saved the worst for last. Swift will let you step right back into the last century by declaring an implicitly unwrapped variable, as follows:

var dangerWillRobinson: String!

The variable dangerWillRobinson is an optional with none of the normal safeguards. You can still treat it an optional—compare it to nil, conditionally bind it, and use optional chaining—but you aren’t required to. If you use the variable by name, it is automatically unwrapped. If it isnil, the results can range from the amusing to the catastrophic.

There’s a place for implicitly unwrapped variables, but they should be your last choice. In order of preference:

· Use non-optional variables whenever possible. Swift ensures they will always contain a valid value. This eliminates all ambiguity.

· For values that could legitimately be absent or you need to create the variable well before it can be initialized, use an optional.

· Reserve implicitly unwrapped optionals for values that can’t immediately be initialized, but you can reasonably guarantee will be valid before being used.

Interface Builder makes use of implicitly unwrapped variables. Whenever you use the @IBOutlet modifier, it requires the variable to be implicitly unwrapped. You’ve seen these countless times in the book so far, like this example:

@IBOutlet var label: UILabel!

The variable can’t be set when the view controller object is created. But it will be set by the outlet connection when the scene is loaded from the storyboard. So, by the time your code executes, it will (should!) have a value, and your code can safely assume it has a value.

Unwrapping has some good qualities. It can, if careful used, simplify your code by turning optionals back into non-optional values. Revisiting the UIImage issue, let’s say you have an image resource that is a permanent part of your app. There’s no reason to assume that the image can’t be loaded. You can use unwrapping to turn that back into the regular value that you know it is, as shown in the following code:

let placeholderImage = UIImage("placeholder")!

The ! blindly unwraps the optional and returns its value, which we trust is always valid.

If you’re nervous about an implicitly unwrapped variable, consider adding assert statements to your code. The following code assumes the CheshireCat resource exists but hedges the bet by adding an assert statement:

var cheshireImage: UIImage! = UIImage(named: "CheshireCat")
assert(cheshireImage != nil, "Unable to load CheshireCat resource")
catView.image = cheshireImage

If the CheshireCat image can’t be loaded for some reason, the assert condition will be false, your program will immediately stop, and you’ll catch the problem right away—or at least during development.

Type Casting

Occasionally, you’ll find yourself with a variable of some base type, like IceCream, that actually has a BananaSplit object in it. You might have a need to interact with that as a BananaSplit object, giving you access to the properties and methods of the specific subclass. Treating one type as if it were another is called type casting. Swift has tools to probe the class of a variable and cast it to another type.

If you’re simply interested in knowing whether the class of an object is actually a specific subclass, use the is operator. The following example creates objects with three different classes, all compatible with the IceCream class:

let cone = IceCream()
let sundae = IceCreamSundae()
let split = BananaSplit()

let mysteryDessert1: IceCream = cone
let mysteryDessert2: IceCream = sundae
let mysteryDessert3: IceCream = split

mysteryDessert1 is IceCreamSundae // false
mysteryDessert2 is IceCreamSundae // true
mysteryDessert3 is IceCreamSundae // true

mysteryDessert1 is BananaSplit // false
mysteryDessert2 is BananaSplit // false
mysteryDessert3 is BananaSplit // true

BananaSplit is a subclass of IceCreamSundae, which is a subclass of IceCream. All three were assigned to IceCream variables. The is operator evaluates to true if the object is actually the class, or a subclass, of the given type. cone is neither an IceCreamSundae nor aBananaSplit. sundae is an IceCreamSundae but not a BananaSplit. split is both a BananaSplit and an IceCreamSundae.

Note Swift will not let you write the tautology split is BananaSplit. The split variable is already a BananaSplit type, so it must—by definition—be a BananaSplit object (or a subclass).

Downcasting

Knowing an object’s class is interesting, but what you really want to do is to work with the properties and functions of the specific subtype. When you assigned split to mysteryDessert3, Swift upcast the object; it took a BananaSplit object and stored it in the more generic (but compatible) IceCream variable. To work with mysteryDessert3 as a BananaSplit object again, you must downcast the object, as follows:

let mySundae = mysteryDessert2 as? IceCreamSundae

The as? operator examines the object and determines whether it’s compatible with the type. If it is, it downcasts the object and returns the same object but with the type IceCreamSundae. Now you can do anything with mySundae that you could with sundae. The as? operator, as you might have guessed, returns an optional. If the object can’t be safely downcast, it returns nil. Technically, the type of the expression object as? Type is Type?. The following demonstrates the use of downcasting. It’s from the Shapely app in Chapter 11.

@IBAction func addShape(sender: AnyObject!) {
if let button = sender as? UIButton {
...
}
}

Objective-C doesn’t use strong typing the way Swift does. Consequently, a lot of parameters and properties in Objective-C objects are simply AnyObject—a generic type that can hold any object reference. To be useful, you must downcast the value to something interesting. InaddShape(_:), the sender parameter is the UIControl that sent the action. We only connected UIButton objects to this action, so the sender should be a UIButton (or some subclass). The if let button = sender as? UIButton checks to make sure it is aUIButton, downcasts it, binds it to the button variable, and runs your code, all in a single statement. If, for some reason, sender isn’t a UIButton, your action doesn’t do much—but it also doesn’t crash.

Note The expression object as? Type will also return nil if object is nil. In the let button = sender as? UIButton statement, sender is an implicitly unwrapped optional. That statement also protects your code from the possibility that sender is nil.

A neat trick is to combine the optional downcast operator with optional chaining, like this:

(mysteryDessert2 as? IceCreamSundae)?.nuts = true

The downcast operator has a dangerous sibling: the forced downcast operator. It works the same way that as? does, but it doesn’t return an optional; it simply assumes the downcast will be successful, the way that ! assumes your optional contains a value. Use it where you are absolutely positive the downcast will work, as follows:

let string = "We want ice cream."
let screaming = (string as NSString).uppercaseString

if mysteryDessert2 is IceCreamSundae {
let mySundae = mysteryDessert2 as IceCreamSundae
mySundae.nuts = true
}

It’s always safe to treat a String as an NSString or an Array as an NSArray. In the second example, the if statement has definitively determined that mysteryDesssert2 is an IceCreamSundae, so the expression as IceCreamSundae will always be successful. However, I recommend using binding and optional downcasting to do this because it’s shorter, safer, and easier to read.

Downcasting Collections

An array or dictionary is just another type, and you downcast collections the same way you downcast objects. Objective-C arrays and dictionaries are not typed the way Swift’s are. Consequently, any time you receive a collection from an Objective-C object it will be a generic[AnyObject] array or an [AnyObject:AnyObject] dictionary. You can downcast it to something more specific, as shown here. (You can find additional examples in the Learn iOS Development Projects image Ch 20 image Casting.playground file.)

UIImagePickerController.availableMediaTypesForSourceType(.PhotoLibrary) as [String]

The availableMediaTypesForSourceType(_:) function returns a typical [AnyObject] Objective-C array. To use it as an array of String objects, you downcast it to [String].

Note When you downcast a collection, Swift checks the type of every element in the collection to ensure that they are all compatible with that type.

You’ve already done this in the SpaceSalad project from Chapter 14. A touch event contains a collection of all of the touch points. These are UITouch objects, but since UIEvent is an Objective-C class, allObjects is a generic array. You turned it into the array of UITouch objects with the following expression:

let fingers = touches.allObjects as [UITouch]

Value vs. Reference vs. Constant vs. Variable

Swift types come in two flavors: value and reference. A value type is a variable that stores a value, like an integer or a structure. Simple enough. A reference type is a value that stores a reference to a value. Classes are reference types. A variable with a UILabel object does not contain thatUILabel object. The UILabel object is allocated somewhere in dynamic memory, and the variable contains a reference to that object.

The reason this is a big deal is when you start passing values around in parameters and storing them in other variables. Here are the basic rules:

· Value types are always copied. Pass an Int variable in an argument of a function call, and the parameter will be a copy of that integer value. You can change the original integer variable, or the parameter, and not affect the other.

· Reference types always refer to the same object. Pass an object variable in an argument of a function call, and the parameter will refer to the same object. Changes to the object are seen by all references to it.

· Even though strings, arrays, and dictionaries are objects (behind the scene—don’t tell anyone I told you that), Swift treats them as value types. If you pass an array to a function and modify that array, you’re modifying a copy of the array.

Knowing when you’re making a copy of a value or passing a reference to the same value is sometimes important. It’s particularly important with mutable objects. For example, if you use a collection object like NSMutableSet, pass that object to a function, and that function changes the set, when the function returns, your set will have been modified. That won’t happen if you’d used an array (value type).

Imaging another situation where you’ve created an NSMutableAttributedString and then use that formatted string for your UIButton. The button now has a reference to the same mutable attributed string. What happens if you then modify your attributed string object again?

Actually, nothing happens. The Cocoa Touch framework authors aren’t stupid, and they know this can be a problem. There are two techniques for preventing this kind of confusion, and you’ll see them throughout iOS.

Many primitive types are immutable. The UIColor, UIFont, NSURL, and many more classes all create immutable objects. Once you have a UIColor object you can’t change its color. The advantage is that you can use this object’s reference in as many places as you like. Because no one can change it, it can’t affect anything else that’s using it.

Properties like attributedString in the UILabel class make copies of the object when you set them. So when you set the attributedString for the UIButton’s title, the UIButton object made a copy of your attributed string and kept the copy. You’re now free to change the original; it won’t affect the button.

Use these same techniques in your code. If you don’t want a parameter or property to be affected by later changes to an object, either copy the object when you get it or use immutable objects. Swift has a special @NSCopying keyword you can add to stored properties, as follows. It causes a copy of the object to be made when it’s set.

class SafeClass: NSObject {
@NSCopying var fancyTitle: NSAttributedString?
}

let and var References

In Swift, let creates a constant (an immutable value), and var creates a variable (a mutable value). So, why can you write the following code?

let button = sender as UIButton
button.enabled = false

button is a constant UIButton object. So, why can you modify the UIButton? That’s because button is a constant reference to a mutable UIButton object. You can change the button object the variable refers to; you just can’t change the variable so it later refers to a differentUIButton object.

Because of this, you’ll see let used extensively throughout Swift for objects you have every intention of modifying. Conversely, you can’t write the following:

let companyName = "Yahoo"
companyName.append(Character("!")) // <-- invalid, companyName can't be modified

In Swift, a string is a value type. A let string is immutable and can’t be changed. The same is true for arrays and dictionaries. This is not true for Objective-C collections. Those are regular objects. A let reference to an NSMutableArray is still modifiable.

var Parameters

Normally, parameters to a function call are constants. The parameter values cannot be modified in the body of the function. I bet you hadn’t even noticed. That’s because the parameters to your function are invariably the input for what your function does. You use that input to do something, you rarely do something to your input. But there are two techniques that let you do just that.

The first is to declare a variable parameter using the var keyword. It doesn’t change how the parameter works, but the parameter’s value is mutable in the body of your function. The following is an example from the Learn iOS Development Projects image Ch 20 imageReferences.playground file:

func pad(var # string: String, with char: Character, var # count: Int) -> String {
while count > 0 {
string.append(char)
count--
}
return string
}

Normally, you wouldn’t be able to use the append(_:) function on the string parameter or decrement the count parameter. By specifying that these are var parameters, they become mutable, local variables.

Note that the string parameter is a value parameter and still gets copied when the function is called. So, the string you’re modifying in the function is not the string that was passed as the argument. You can verify that with the following example:

let originalString = "Yahoo"
let paddedString = pad(string: originalString, with: "!", count: 4)

After this code executes, originalString is still “Yahoo.” But what if you did want to modify the original string? There’s a way to do that too.

References to Values (inout)

You’ve already seen how closures create references to your existing values, even value types. You can do something similar in function parameters. If you mark your parameter with the inout keyword, it turns your value parameter into a reference parameter. Here’s an example:

func padSurPlace(inout # string: String, with char: Character, var # count: Int) -> String {
while count > 0 {
string.append(char)
count--
}
return string
}

The inout keyword turns the string parameter into a reference to a String value. When you call the function, you prefix the variable with an & (ampersand), as follows. This is your visual clue that you’re passing a reference to the variable, not a copy of its value.

var mutableString = "Yahoo"
padSurPlace(string: &mutableString, with: "!", count: 3)

When the padSurPlace(string:,with:,count:) function executes, its string parameter is referring to the variable you passed in. Any changes made affect the original. After this code executes, the value of mutableString will be “Yahoo!!!” This works with any type.

Caution If you make a parameter inout, it can only be used with mutable variables. You can’t pass a constant or a literal value for that argument.

Working with C and Objective-C

Swift works so seamlessly with C and Objective-C that there’s very little you need to know about either in order to write apps in Swift. In fact, almost everything you’ve used in this book so far, save what you wrote in Swift, is probably an Objective-C class or C function.

Swift can use any Objective-C class as if it were a Swift class. Objective-C can use most Swift classes as if they were Objective-C classes. If you add Swift to an Objective-C project, or vice versa, Xcode automatically generates translation interfaces that describe your Swift classes to Objective-C and your Objective-C classes to Swift.

There are only a couple of things I want to mention here. If you need to know anything else about how Swift, Objective-C, and C all work together, refer to Apple’s Using Swift with Cocoa and Objective-C, also available for free in iBooks. This is the companion to The Swift Programming Language. It will answer all of your cross-language questions, and probably a few you didn’t think of.

The Toll-Free Bridge

In Swift you can seamlessly use Objective-C methods right alongside C functions from Core Foundation. This means you can easily have a mix of Swift values, Objective-C objects, and Core Foundation types. A few of these types overlap and are interchangeable. Table 20-4 lists the Swift, Objective-C, and C types that are equivalent.

Table 20-4. Toll-Free Bridge Types

Swift

Objective-C

C

Array

NSArray

CFArrayRef

NSAttributedString

CFAttributedStringRef

NSCharacterSet

CFCharacterSetRef

NSData

CFDataRef

NSDate

CFDateRef

Dictionary

NSDictionary

CFDictionaryRef

NSMutableArray

CFMutableArrayRef

NSMutableAttributedString

CFMutableAttributedStringRef

NSMutableCharacterSet

CFMutableCharacterSetRef

NSMutableData

CFMutableDataRef

NSMutableDictionary

CFMutableDictionaryRef

NSMutableSet

CFMutableSetRef

NSMutableString

CFMutableStringRef

NSNumber

CFNumberRef

NSSet

CFSetRef

String

NSString

CFStringRef

NSURL

CFURLRef

This is not a complete list, but it includes the common ones. You already ran into this in your MyStuff app when setting up the image picker in Chapter 7. The mediaTypes property of the image picker is an array of URI types. These are defined in the Core Foundation as CFStringRefvalues. To use this in your app, you had to write code like the following:

picker.mediaTypes = [kUTTypeImage as NSString, kUTTypeMovie as NSString]

The kUTTypeImage symbol is a Core Foundation string value, but you can substitute it anywhere an NSString or String type is expected just by casting it to the desired type.

In another quick example, let’s say you’ve received a CFUUIDRef type (a Core Foundation Universally Unique Identifier) from a framework. You’d prefer that as a Swift String instead. There’s a Core Foundation function to convert the CFUUIDRef into a CFStringRef. All you have to do is cast the returned CFStringRef to the type you want, as shown in the following code:

let uuid = CFUUIDCreate(nil)
let uuidString: String = CFUUIDCreateString(nil,uuid) as String

Method Signatures

Methods in Objective-C and functions in Swift all have a signature. A signature is the portion of the function name that identifies it. Signatures are used to match a function call to a function. They are also used as selectors, values used to dynamically choose a method to execute.

Swift signatures have their roots in Objective-C signatures, so let’s start there. The following method is defined in the Objective-C UIImage class:

- (void)drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)mode alpha:(CGFloat)alpha

Compare this to the same method in Swift’s UIImage class.

func drawAtPoint(_ point: CGPoint, blendMode mode: CGBlendMode, alpha alpha: CGFloat)

I’ve highlighted the significant keywords in both. The signature for both of these functions is as follows:

drawAtPoint:blendMode:alpha:

Notice that local parameter names are not part of the signature. Only the function name and the external parameter names are significant. When you want to unambiguously identify a function in Swift, you write the function using only its name and external parameter names, like this:drawAtPoint(_:,blendMode:,alpha:).

Method signature are still used in the Cocoa Touch framework, although their use is dwindling thanks to closures. If you do need to specify one, you form it as a string. (Swift lacks the special method selector type used by Objective-C.) You did this in the Shapely app in Chapter 11, as follows:

let pan = UIPanGestureRecognizer(target: self, action: "moveShape:")

The action parameter is a method selector, written as a Swift string, that causes this gesture recognizer to call the moveShape(_:) function when activated.

Note The colons in a selector indicate parameters. If your class has two functions, setNeedsIceCream() that takes no parameters and setNeedsIceCream(_ want: Bool) that takes one parameter, their signatures are distinguished by the trailing colon:setNeedsIceCream vs. setNeedsIceCream:.

Memory Management

The fact that I’ve written this entire book—up to this point—without even mentioning memory management is nothing short of amazing. Memory management in iOS originally placed a great deal of the burden on the programmer. That has since improved, with the recent introduction of Automatic Reference Counting (ARC), but even then there were a significant number of exceptions, restrictions, and caveats.

Swift starts over with a clean slate. iOS, and thus Swift, still uses ARC. But Swift handles ARC so flawlessly that there’s really nothing for the programmer to do, except repurpose that portion of their brain they used to dedicate to memory management for something more enjoyable.

This is not to say that you don’t need to know anything about memory management in iOS. A cursory understanding is extremely helpful. ARC is a wonderful technology, but is has a Persian flaw. There are situations where you can create memory leaks in your app. And the tools you use to combat those leaks have other, sometimes unwanted, side effects. So, welcome to Memory Management 101. (Don’t fret, this is quick course.)

Garbage Collection

In the beginning, there was manual memory management. The programmer was responsible for allocating every block of memory they needed and later releasing it back to the system when they were done with it. As program complexity grew, it quickly became obvious this wasn’t an efficient solution. Oh, and programmers got really tired of writing the same code over and over again.

What followed were various forms of automatic memory management. One of those is called garbage collection. Garbage collection takes responsibility for recycling the values and objects you are no longer using by returning that memory to the operating system. The next time you need to create an object or concatenate a string, there’s memory available to do that.

Conceptually, garbage collection is simple. In the example illustrated in Figure 20-3, you have two button objects. These, in turn, have references to attributed strings that, in turn, have references to strings, dictionaries, and font objects.

image

Figure 20-3. Object references in an app

Now you decide to change the title of a button. You create a new attributed string, possibly reusing string and font objects you’ve used before, and assign the new object to the attributedString property of the button, as shown in Figure 20-4.

image

Figure 20-4. Replacing an attributed string object

The question becomes, what does Swift do with the old attributed string object? It’s no longer being used. If it, and every other unused object, were allowed to continue occupying memory, your app would soon run out of memory and crash. In fact, just about every app in the world would quickly run out of memory.

What needs to happen is for the objects you’re no longer using to be destroyed and their memory recovered. But what does it mean to be “no longer used?” In this example, it’s a curious mix. Obviously, the old attributed string object is no longer serving any purpose. Neither are its string and dictionary objects. But the string and font objects the dictionary refers to are still being used by other objects. So, you can’t simply destroy the old attributed string object and everything it references.

One solution is to determine the graph of objects that are in use. That consists of the root objects of your application (your UIApplication object), all of the objects it references (your view controller objects), all of the objects they reference (view objects), and all of the objects they reference (strings, fonts, colors, and so on). When you’re done, you have the complete set of every object your app is using. These are called the reachable objects. Everything else is garbage, as shown in Figure 20-5.

image

Figure 20-5. Garbage collection

This is traditional garbage collection. The awesome feature of garbage collection is that you, the programmer, don’t have do to anything. You just create and use the objects you want. As soon as you stop using an object, the operating system disposes of it for you. That sounds a lot like the code you’ve been writing in Swift. So, Swift must be using garbage collection, right?

Unfortunately, this kind of memory management is too computationally intensive to make an efficient solution for mobile devices. iOS uses a different kind of memory management that tries to accomplish the same thing garbage collection does but with much less overhead.

Reference Counting

iOS uses a technique called reference counting. In reference counting, all objects maintain a reference count. The reference count is the number of objects that are still using (have a reference to) that object. If you assign an object to a property, it increments the reference count. When you remove the object from the property, the reference count is decremented. When the reference count hits zero, there are no longer any references to the object and it is destroyed. Swift does this, automatically, for every object reference.

Figure 20-6 shows the same set of objects as those in Figure 20-3, but this time using reference counting. All of the objects have nonzero reference counts and are therefore still in use.

image

Figure 20-6. Objects with reference counts

When you assign a new attributed string to the button, here’s what happens. The new object’s reference count is incremented and stored as the new property value, as shown in Figure 20-7. This is called a retain. While the attributed string was being constructed, it retained all of the objects it references, also shown in Figure 20-7.

image

Figure 20-7. Retaining new objects

The reference count of the previous property value is then decremented, as shown in Figure 20-8. This is called a release. Since the button was its only reference, its count goes to zero, and the object is destroyed. During destruction, it releases any objects it was referencing, and the process repeats.

image

Figure 20-8. Releasing old objects

When the whole thing is over, the old attributed string object is gone, as are the string and dictionary objects it was using. But the string and font objects the dictionary was referencing are still with us because they continue to be referenced by other objects.

Reference counting is fast, simple, and efficient, and the end result is the same as garbage collection. Well, it’s the same most of the time. There’s one situation where reference counting doesn’t work so well, and you need to know about it.

Circular Retains

Let’s look at a different problem. You’re creating an enrollment system. You have Teacher objects and Student objects. The teacher has a reference to each student, and the students all have a reference to their teacher. These objects and their reference counts are shown in Figure 20-9.

image

Figure 20-9. Circular references

Each Student has a retain count of one (for the teacher’s reference). The Teacher has a reference count of four—one from its owner and three from its three students.

The owner is now done with these objects and releases Teacher, as shown in Figure 20-10. This releases the teacher object, decrements its reference count, and then...nothing. The teacher’s reference count is still three, so it isn’t destroyed. Because it’s not destroyed, it never releases its student objects, so they never release their teacher.

image

Figure 20-10. Releasing the Teacher object

This is called a circular retain cycle. It’s also called a memory leak. These objects will continue to exist forever, and there’s no way to get rid of them, short of terminating your app.

There is a way out of this trap. The solution is to not have the Student objects retain the Teacher object. Swift provides a special type called a weak reference; it’s an object reference that doesn’t retain the object it references. The regular kind of reference is called a strong reference.

Let’s replace the student’s teacher reference with a weak reference and see what happens, as shown in Figure 20-11.

image

Figure 20-11. Using weak references

The weak references still contain Teacher values, but these do not increment its reference count. Now when the teacher object is released, it gets destroyed, and it destroys all of the student objects it was referencing. The following statement declares a weak reference:

weak var teacher: Teacher?

Boom! Problem solved. But you know the old saying, “Every great solution creates its own problem.” Or maybe they don’t say that; maybe that was just me. Regardless, weak references have their own set of issues. Here’s what you need to know:

· A weak reference refers to an object but does not retain it.

· If the object in a weak reference is destroyed, the value is silently set to nil.

· A weak reference must be an optional or implicitly unwrapped optional (because it could be set to nil at any time).

Weak references are perfect for “tree” or “parent-child” object relationships, where the child maintains a reference to its parent. Another place you’ll find weak references used is in delegate and data source properties. In practice—and you’ve done this throughout the book—an object’s delegate object is often itself or its parent object, like a view controller. This creates the same kind of circular retain cycle shown in Figure 20-9. (Yes, an object can retain itself.)

But this too has consequences. You already dealt with this problem in the Wonderland app from Chapter 12. In the BookViewController.swift file, you created a property to store your book view’s data source, as follows:

let bookSource = BookDataSource()
...
dataSource = bookSource

Later, you assigned the bookSource to your page view controller’s dataSource but kept the same reference in the bookSource property. That’s because dataSource is a weak reference. If you don’t have at least one strong reference to your BookDataSource object, it will be immediately destroyed, and your page view controller won’t have a data source. Believe me, this kind of problem can be maddening to debug.

Retain cycles can be subtle. Another place they can occur is in closures, where the closure refers to the object that owns the closure. There’s an extensive section in The Swift Programming Language on circular retains. Now that you understand the problem, take a moment to breeze through that section.

And just as the optional has its implicitly unwrapped sibling, weak references also have a dangerous cousin. An unowned variable is a non-optional variable with a weak reference. You declare an unowned variable using the unowned keyword, as follows:

unowned var teacher: Teacher = ...

As you might guess, you’d use this only when you are absolutely sure that the object in the reference won’t be destroyed before you might use it again. If you use this variable after the Teacher object is destroyed, your app will crash. Worse, it’s not an optional; there’s no way to test to see whether it’s nil. Consider using a weak implicitly unwrapped variable instead.

Even More Swift

But wait, there’s more! There is a lot to the Swift language, as witnessed by the length of this chapter—a chapter that’s supposed to be a “quick” introduction. And yet, I still didn’t get to some of the good stuff. Here are a few more topics you’ll want to explore as your Swift skills mature:

· A type alias creates a new name for an existing type, much like C’s typedef.

· You can overload operators. A class, for example, can define its own code for the == and != operators, essentially defining what it means for two objects of that class to be “equal.”

· You can create your own operators. That’s right; you can just make up operators. If you feel that your enumeration needs a +&- operator so that you can write myEnum +&- 3, go for it. (I’m pitying the next programmer who has to figure out what that means.)

· Functions can have variadic parameters. That’s a fancy name for a function that accepts a variable number of parameters, like the NSString(format:,_:...) initializer. The ... indicates that you can call the function with as many additional parameters as you want.

· Swift supports generics. A generic is a type that can mutate to deal with different types in a type-safe manner. In English, you can create a class that works with different types of objects. When you use that class, you tell it what type you’re working with, and it’s as if Swift creates a new subclass of your class just for that type. All of the collection types in Swift are generics. There’s only one Array type, but when you declare an array of UITouch objects ([UITouch]), Swift creates an array that only stores UITouch objects and nothing else.

· There’s a suite of byte access types that gives you most of the power of C pointers. You can use the byte access types to work with raw data, like image pixel buffers, and interact with C functions that still deal with pointers.

Summary

You’ve learned a lot about Swift. And I mean, a lot—enough to write professional-level iOS apps. I also don’t expect you to memorize everything in this chapter the first time around. Most developers, myself included, learned these programming language lessons over the course of many years. Use this chapter as a reference or just come back when things feel fuzzy.

I think it’s time to take all of this new Swift knowledge and do something exceptional with it, like create a framework.

EXERCISE

I mentioned in the “switch Statement” section that a tuple cases can contain a combination of constants, expressions, wildcards, bindings, and ranges. Take the switch statement example that used where clauses and rewrite it using just tuple patterns.

You’ll find my solution in the Control E1.playground file.

1Binary compatible means that code written in Swift can directly call existing C functions and use Objective-C objects, and vice versa.