Flow Control and More - Language - iOS 8 Programming Fundamentals with Swift: Swift, Xcode, and Cocoa Basics (2015)

iOS 8 Programming Fundamentals with Swift: Swift, Xcode, and Cocoa Basics (2015)

Part I. Language

Chapter 5. Flow Control and More

This chapter presents the miscellaneous remaining aspects of the Swift language. I’ll start by describing the syntax of Swift’s flow control constructs for branching and looping. Then I’ll talk about how to override operators and how to create your own operators. The chapter ends with a survey of Swift’s privacy and introspection features and some specialized modes of reference type memory management.

Flow Control

A computer program has a path of execution through its code statements. Normally, this path follows a simple rule: execute each statement in succession. But there is another possibility. Flow control can be used to make the path of execution skip some code statements, or repeat some code statements. Flow control is what makes a computer program “intelligent,” and not merely a simple fixed sequence of steps. By testing the truth value of a condition — an expression that evaluates to a Bool and is thus true or false — the program decides at that moment how to proceed. Flow control based on testing a condition may be divided into two general types:

Branching

The code is divided into alternative chunks, like roads that diverge in a wood, and the program is presented with a choice of possible ways to go: the truth of a condition is used to determine which chunk will actually be executed.

A compact form of branching is conditional evaluation. In determining a value, such as the value to be assigned to a variable, the code is divided into two expressions: the truth of a condition is used to determine which expression will be evaluated and used as the value.

Looping

A chunk of code is marked off for possible repetition: the truth of a condition is used to determine whether the chunk should be executed, and then whether it should be executed again. Each repetition is called an iteration. Typically, some feature of the environment (such as the value of a variable) is changed on each iteration, so that the repetitions are not identical, but are successive stages in progressing through an overall task.

The chunks of code in flow control, which I refer to as blocks, are demarcated by curly braces. These curly braces constitute a scope. New local variables can be declared here, and go out of existence automatically when the path of execution exits the curly braces. For a loop, this means that local variables come into existence and go out of existence on each iteration. As with any scope, code inside the curly braces can see the surrounding, higher scope.

Swift flow control is fairly simple, and by and large is similar to flow control in C and related languages. There are two fundamental syntactic differences between Swift and C, both of which make Swift simpler and clearer: in Swift, a condition does not have to be wrapped in parentheses, and the curly braces can never be omitted. Moreover, Swift adds some specialized flow control features to help you grapple more conveniently with Optionals, and boasts a particularly powerful form of switch statement.

Branching

Swift has two forms of branching: the if construct, and the switch statement. Conditional evaluation is a compact form of if construct.

If construct

The Swift branching construct with if is similar to C. Many examples of if constructs have appeared already in this book. The construct may be formally summarized as shown in Example 5-1.

Example 5-1. The Swift if construct

if condition {

statements

}

if condition {

statements

} else {

statements

}

if condition {

statements

} else if condition {

statements

} else {

statements

}

The third form, containing else if, can have as many else if blocks as needed, and the final else block may be omitted.

Here’s a real-life if construct that lies at the heart of one of my apps:

// okay, we've tapped a tile; there are three cases

if self.selectedTile == nil { // no other selected tile: select and play

self.selectTile(v)

let url = v.layer.valueForKey("song") as! NSURL

let item = AVPlayerItem(URL:url)

self.player = AVPlayer(playerItem:item)

self.player!.play()

} else if self.selectedTile == v { // selected tile was tapped: deselect

self.deselectAll()

} else { // there was one selected tile and another was tapped: swap

let v1 = self.selectedTile!

self.selectedTile = nil

let v2 = v

self.swap(v1, with:v2, check:true, fence:true)

}

Conditional binding

In Swift, if can be followed immediately by a variable declaration and assignment — that is, by let or var and a new local variable name, possibly followed by a colon and a type declaration, then an equal sign and a value. This syntax, called a conditional binding, is actually a shorthand for conditionally unwrapping an Optional. The assigned value is expected to be an Optional — the compiler will stop you if it isn’t — and this is what happens:

§ If the Optional is nil, the condition fails and the block is not executed.

§ If the Optional is not nil, then:

1. The Optional is unwrapped.

2. The unwrapped value is assigned to the declared local variable.

3. The block is executed with the local variable in scope.

Thus, a conditional binding is a convenient shorthand for safely passing an unwrapped Optional into a block. The Optional is unwrapped, and the block is executed, only if the Optional can be unwrapped.

It is perfectly reasonable and common for the local variable in a conditional binding to have the same name as an existing variable in the surrounding scope. It can even have the same name as the Optional being unwrapped! Indeed, giving the local variable the same name as the Optional is a good thing to do, because there is no need to make up a new name, and inside the block the unwrapped value of the Optional overshadows the original Optional, which thus cannot be accessed accidentally.

Here’s an example of a conditional binding. Recall this code from Chapter 4, where I optionally unwrap an NSNotification’s userInfo dictionary, attempt to fetch a value from the dictionary using the "progress" key, and proceed only if that value turns out to be an NSNumber:

let prog = n.userInfo?["progress"] as? NSNumber

if prog != nil {

self.progress = prog!.doubleValue

}

I’ll rewrite that code with the help of conditional bindings. The result is somewhat more verbose and is rather deeply indented — Swift programmers like to call this the “pyramid of doom” — but in my view it is also considerably more legible, because the structure reflects perfectly the successive stages of testing:

if let ui = n.userInfo {

if let prog : AnyObject = ui["progress"] {

if prog is NSNumber {

self.progress = (prog as! NSNumber).doubleValue

}

}

}

In that example, we can actually eliminate one level of nesting, and in my real code, I would do so. Recall that the as? operator yields an Optional. This means that the result of the as? operator can be assigned into a conditional binding. Thus, we can safely unwrap and cast a value in a single move:

if let ui = n.userInfo {

if let prog = ui["progress"] as? NSNumber {

self.progress = prog.doubleValue

}

}

If an AnyObject is an NSNumber, you can cast all the way down from AnyObject to a Swift numeric type in a single move, avoiding any mention of NSNumber:

if let ui = n.userInfo {

if let prog = ui["progress"] as? Double {

self.progress = prog

}

}

New in Swift 1.2, the “pyramid of doom” can be flattened still further: successive conditional bindings can be combined into a list, separated by comma:

if let ui = n.userInfo, prog = ui["progress"] as? Double {

self.progress = prog

}

A binding in the list can even be followed by a where clause whose content can be any Bool expression at all, thus effectively folding yet another condition into the line. And the entire list can start with a condition, before the word let or var is encountered. Here’s a real-life example from my own code (which I’ll explain further in Chapter 11). Before the Swift 1.2 extended conditional binding syntax, I had four nested conditions:

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<()>) {

if keyPath == "readyForDisplay" {

if let obj = object as? AVPlayerViewController {

if let ok = change[NSKeyValueChangeNewKey] as? Bool {

if ok {

// ...

}

}

}

}

}

With the extended conditional binding syntax, those four conditions can be combined into one:

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<()>) {

if keyPath == "readyForDisplay",

let obj = object as? AVPlayerViewController,

let ok = change[NSKeyValueChangeNewKey] as? Bool where ok {

// ...

}

}

Switch statement

A switch statement is a neater way of writing an extended if...else if...else construct. In C (and Objective-C), a switch statement contains hidden traps; Swift eliminates those traps, and adds power and flexibility. As a result, switch statements are commonly used in Swift (whereas they are relatively rare in my Objective-C code).

In a switch statement, the condition consists in the comparison of different possible values, called cases, against a single value, called the tag. The case comparisons are performed successively in order. As soon as a case comparison succeeds, that case’s code is executed and the entire switch statement is exited. The schema is shown in Example 5-2; there can be as many cases as needed, and the default case can be omitted (subject to restrictions that I’ll explain in a moment).

Example 5-2. The Swift switch statement

switch tag {

case pattern1:

statements

case pattern2:

statements

default:

statements

}

Here’s an actual example:

switch i {

case 1:

println("You have 1 thingy!")

case 2:

println("You have 2 thingies!")

default:

println("You have \(i) thingies!")

}

In that code, a variable i functions as the tag. The value of i is first compared to the value 1. If it is 1, that case’s code is executed and that’s all. If it is not 1, it is compared to the value 2. If it is 2, that case’s code is executed and that’s all. If the value of i matches neither of those, thedefault case’s code is executed.

In Swift, a switch statement must be exhaustive. This means that every possible value of the tag must be covered by a case. The compiler will stop you if you try to violate this rule. The rule makes intuitive sense when a value’s type allows only a limited number of possibilities; the usual example is an enum, which itself has a small, fixed set of cases as its possible values. But when, as in the preceding example, the tag is an Int, there is an infinite number of possible individual cases. Thus, a “mop-up” case must appear, to mop up all the cases that you didn’t write explicitly. A common way to write a “mop-up” case is to use a default case.

Each case’s code can consist of multiple lines; it doesn’t have to be a single line, as the cases in the preceding example happen to be. However, it must consist of at least a single line; it is illegal for a Swift switch case to be completely empty. It is legal for the first (or only) line of a case’s code to appear on the same line as the case, after the colon; thus, I could have written the preceding example like this:

switch i {

case 1: println("You have 1 thingy!")

case 2: println("You have 2 thingies!")

default: println("You have \(i) thingies!")

}

The minimum single line of case code is the keyword break; used in this way, break acts as a placeholder meaning, “Do nothing.” It is very common for a switch statement to include a default (or other “mop-up” case) consisting of nothing but the keyword break; in this way, you exhaust all possible values of the tag, but if the value is one that no case explicitly covers, you do nothing.

Now let’s focus on the comparison between the tag value and the case value. In the preceding example, it works like an equality comparison (==); but that isn’t the only possibility. In Swift, a case value is actually a special expression called a pattern, and the pattern is compared to the tag value using a “secret” pattern-matching operator, ~=. The more you know about the syntax for constructing a pattern, the more powerful your case values and your switch statements will be.

A pattern can include an underscore (_) to absorb all values without using them. An underscore case is thus an alternative to a default case:

switch i {

case 1:

println("You have 1 thingy!")

case _:

println("You have many thingies!")

}

A pattern can include a declaration of a local variable name (an unconditional binding) to absorb all values and use the actual value. This is another alternative to a default case:

switch i {

case 1:

println("You have 1 thingy!")

case let n:

println("You have \(n) thingies!")

}

When the tag is a Comparable, a case can include a Range; the test involves sending the Range the contains message:

switch i {

case 1:

println("You have 1 thingy!")

case 2...10:

println("You have \(i) thingies!")

default:

println("You have more thingies than I can count!")

}

When the tag is an Optional, a case can test it against nil. Thus, a possible way to unwrap an Optional safely is to test against nil first and then unwrap in a subsequent case, since we’ll never reach the unwrapping if the nil test succeeds. In this example, i is an Optional wrapping an Int:

switch i {

case nil: break

default:

switch i! {

case 1:

println("You have 1 thingy!")

case let n:

println("You have \(n) thingies!")

}

}

When the tag is a Bool, a case can test it against a condition. Thus, by a clever perversion, you can use the cases to test any conditions you like — by using true as the tag! A switch statement thus becomes a genuine substitute for an extended if...else if construct. In this example from my own code, I could have used if...else if, but each case is just one line, so a switch statement seems clearer:

func positionForBar(bar: UIBarPositioning) -> UIBarPosition {

switch true {

case bar === self.navbar: return .TopAttached

case bar === self.toolbar: return .Bottom

default: return .Any

}

}

In that code, we cannot accomplish the same thing by using bar as the tag, because the comparison would not be an === (identity) comparison. Using true as the tag solves the problem very neatly.

A pattern can include a where clause adding a condition. This is often, though not necessarily, used in combination with a binding; the condition limits the truth value of the case, and can refer to the variable declared in the binding:

switch i {

case let j where j < 0:

println("i is negative")

case let j where j > 0:

println("i is positive")

case 0:

println("i is 0")

default:break

}

In that example, we don’t really need the binding at all; it was just to illustrate that the syntax works and that the binding is captured in the condition. We could just as well have used an underscore and involved the tag itself in the condition; this is an alternative to my switch true trick:

switch i {

case _ where i < 0:

println("i is negative")

case _ where i > 0:

println("i is positive")

case 0:

println("i is 0")

default:break

}

A pattern can include the is operator to test the tag’s type. In this example, assume that we have a Dog class and its NoisyDog subclass, and that d is typed as Dog:

switch d {

case is NoisyDog:

println("You have a noisy dog!")

case _:

println("You have a dog.")

}

A pattern can include a cast with the as (not as?) operator. Typically, you’ll combine this with a binding that declares a local variable; despite the use of unconditional as, the value is conditionally cast and, if the cast succeeds, the local variable carries the cast value into the case code. Assume that Dog implements bark and that NoisyDog implements beQuiet:

switch d {

case let nd as NoisyDog:

nd.beQuiet()

case let d:

d.bark()

}

In that pattern, the tag can be an Optional. The as test is applied to the value wrapped inside the Optional, and the assignment to the local variable, if the test passes, unwraps the Optional. Thus, we can test the wrapped value’s type, unwrap the Optional, and assign the unwrapped value to a local variable, all in one move. Here is yet another rewrite of my code for fetching a value from an NSNotification’s userInfo dictionary:

switch n.userInfo?["progress"] {

case let prog as Double:

self.progress = prog

default:break

}

You can also use as (not as!) to cast down the tag (and possibly unwrap it) conditionally as part of a test against a specific match; in this example, i is an AnyObject:

switch i {

case 0 as Int:

println("It is 0")

default:break

}

You can perform multiple tests at once by expressing the tag as a tuple and wrapping the corresponding tests in a tuple. The case passes only if every test in the test tuple succeeds against the corresponding member of the tag tuple. In this example, we start with a dictionary d that comes from Cocoa, so that it is typed as [NSObject:AnyObject]. Using a tuple, we can safely attempt to extract and cast two values at once:

switch (d["size"], d["desc"]) {

case let (size as Int, desc as String):

println("You have size \(size) and it is \(desc)")

default:break

}

When a tag is an enum, the cases can be cases of the enum. A switch statement is thus an excellent way to handle an enum. Here’s an enum:

enum ListType {

case Albums

case Playlists

case Podcasts

case Books

}

And here’s a switch statement, where the tag, type, is a ListType:

switch type {

case .Albums:

println("Albums")

case .Playlists:

println("Playlists")

case .Podcasts:

println("Podcasts")

case .Books:

println("Books")

}

No “mop-up” is needed, because I exhausted the cases. In that example, where the code is outside the enum’s own declaration, the dot before the case names is needed. But if the code is inside the enum’s declaration, the dot can be omitted:

enum ListType : Printable {

case Albums

case Playlists

case Podcasts

case Books

var description : String {

switch self {

case Albums:

return "Albums"

case Playlists:

return "Playlists"

case Podcasts:

return "Podcasts"

case Books:

return "Books"

}

}

}

A switch statement is the only way to extract an associated value from an enum case. Recall this enum from Chapter 4:

enum Error {

case Number(Int)

case Message(String)

case Fatal

}

To extract the error number from an Error whose case is .Number, or the message string from an Error whose case is .Message, I have to use a switch statement. Recall that the associated value is actually a tuple. A tuple of patterns after the matched case name is applied to the associated value. If a pattern is a binding variable, it captures the associated value. The let (or var) can appear inside the parentheses or after the case keyword; this code illustrates both alternatives:

switch err {

case .Number(let theNumber):

println("It is a .Number: \(theNumber)")

case let .Message(theMessage):

println("It is a .Message: \(theMessage)")

case .Fatal:

println("It is a .Fatal")

}

If the let (or var) appears after the case keyword, I can add a where clause:

switch err {

case let .Number(n) where n > 0:

println("It's a positive error number \(n)")

case let .Number(n) where n < 0:

println("It's a negative error number \(n)")

case .Number(0):

println("It's a zero error number")

default:break

}

If I don’t want to extract the error number but just want to match against it, I can use some other pattern inside the parentheses:

switch err {

case .Number(1...Int.max):

println("It's a positive error number")

case .Number(Int.min...(-1)):

println("It's a negative error number")

case .Number(0):

println("It's a zero error number")

default:break

}

To combine case tests (with an implicit logical-or), separate them with a comma:

switch i {

case 1,3,5,7,9:

println("You have a small odd number of thingies.")

case 2,4,6,8,10:

println("You have a small even number of thingies.")

default:

println("You have too many thingies for me to count.")

}

In this example, i is declared as an AnyObject:

switch i {

case is Int, is Double:

println("It's some kind of number.")

default:

println("I don't know what it is.")

}

But you can’t use a comma to combine patterns that declare binding variables, presumably because it isn’t clear what variable should be set to what value.

Another way of combining cases is to fall through from one case to the next by using a fallthrough statement. It is not uncommon for a case to consist entirely of a fallthrough statement, though it is perfectly legal for a case to execute some code and then fall through:

switch pep {

case "Manny": fallthrough

case "Moe": fallthrough

case "Jack":

println("\(pep) is a Pep boy")

default:

println("I don't know who \(pep) is")

}

Note that fallthrough evades the test of the next case; it simply starts executing the next case’s code, directly. Therefore, the next case can’t declare any binding variables, because they would never be set.

Conditional evaluation

An interesting problem arises when you’d like to decide what value to use — for example, what value to assign to a variable. This seems like a good use of a branching construct. You can, of course, declare the variable first using var without initializing it, and then set it within a subsequent branching construct. It would be nice, however, to use a branching construct as the variable’s value. Here, for example, I try (and fail) to write a variable assignment where the equal sign is followed directly by a branching construct:

let title = switch type { // compile error

case .Albums:

"Albums"

case .Playlists:

"Playlists"

case .Podcasts:

"Podcasts"

case .Books:

"Books"

}

There are languages that let you talk that way, but Swift is not one of them. However, an easy workaround does exist — use a define-and-call anonymous function:

let title : String = {

switch type {

case .Albums:

return "Albums"

case .Playlists:

return "Playlists"

case .Podcasts:

return "Podcasts"

case .Books:

return "Books"

}

}()

In the special case where a value can be decided by a two-pronged condition, Swift provides the C ternary operator (:?). Its scheme is as follows:

condition ? exp1 : exp2

If the condition is true, the expression exp1 is evaluated and the result is used; otherwise, the expression exp2 is evaluated and the result is used. Thus, you can use the ternary operator while performing an assignment, using this schema:

let myVariable = condition ? exp1 : exp2

What myVariable gets initialized to depends on the truth value of the condition. I use the ternary operator heavily in my own code. Here’s an example:

cell.accessoryType =

ix.row == self.currow ? .Checkmark : .DisclosureIndicator

The context needn’t be an assignment; here, we’re deciding what value to pass as a function argument:

CGContextSetFillColorWithColor(

context, self.hilite ? purple.CGColor : beige.CGColor)

In the version of C used by modern Objective-C, there’s a collapsed form of the ternary operator that allows you to test a value against nil. If it is nil, you get to supply a substitute value to be used. If it isn’t nil, the tested value itself is used. That’s a very common and convenient thing to do.

In Swift, the analogous operation would involve testing an Optional: if the tested Optional is nil, use the substitute value; if it isn’t nil, unwrap the Optional and use the unwrapped value. Swift has such an operator — the ?? operator (called the nil-coalescing operator).

Recall this example from Chapter 4, where arr is a Swift array of Optional strings and I’m converting it to a form that can be handed over to Objective-C as an NSArray:

let arr2 : [AnyObject] =

arr.map{if $0 == nil {return NSNull()} else {return $0!}}

We can write the same thing much more neatly using the ternary operator:

let arr2 = arr.map{ $0 == nil ? NSNull() : $0! }

But the nil-coalescing operator is even neater:

let arr2 = arr.map{ $0 ?? NSNull() }

The as? operator yields an Optional, so it’s a great candidate for use with the ?? operator. Recall this example from Chapter 4:

let arr2 : [String] = arr.map {

if $0 is String {

return $0 as! String

} else {

return ""

}

}

That code is literally the inverse of the previous example: I’ve received from Cocoa an array of AnyObject, arr, which is a mixed bag of NSString and NSNull objects, and now I want to turn it into an array of String by substituting the empty string for all the NSNull objects. I promised I’d shorten that code; now I’ll do it:

let arr2 = arr.map { $0 as? String ?? "" }

Expressions using ?? can be chained:

let someNumber = i1 as? Int ?? i2 as? Int ?? 0

That code tries to cast i1 to an Int and use that Int. If that fails, it tries to cast i2 to an Int and use that Int. If that fails, it gives up and uses 0.

Loops

The usual purpose of a loop is to repeat a block of code with some simple difference on each iteration. This difference will typically serve also as a signal for when to stop the loop. Swift provides two basic loop structures: while loops and for loops.

While loops

A while loop comes in two forms, schematized in Example 5-3.

Example 5-3. The Swift while loop

while condition {

statements

}

do {

statements

} while condition

The chief difference between the two forms is the timing of test. In the second form, the condition is tested after the block has executed — meaning that the block will be executed at least once.

Usually, the code inside the block will change something that alters both the environment and the condition, thus eventually bringing the loop to an end. Here’s a typical example from my own code (movenda is an array):

while self.movenda.count > 0 {

let p = self.movenda.removeLast()

// ...

}

Each iteration removes an element from movenda, so eventually its count falls to 0 and the loop is no longer executed; execution then proceeds to the next line after the closing curly braces.

Another common use of while loops in my code is to walk my way up or down a hierarchy. In this example, I start with a subview (textField) of some table view cell, and I want to know which table view cell it is a subview of. So I keep walking up the view hierarchy, investigating each superview in turn, until I reach a table view cell:

var v : UIView = textField

do { v = v.superview! } while !(v is UITableViewCell)

After that code, v is the desired table view cell.

The condition in the first form of while loop can be a conditional binding of an Optional. This provides a compact way of safely unwrapping an Optional and looping until the Optional is nil; the local variable containing the unwrapped Optional is in scope inside the curly braces. In this example, I walk up the view hierarchy until I reach the top — the first superview whose superview is nil:

var vv : UIView = self.button

while let v = vv.superview {vv = v}

For loops

A Swift for loop comes in two forms, as schematized in Example 5-4.

Example 5-4. The Swift for loop

for variable in sequence {

statements

}

for before-all; condition; after-each {

statements

}

The first form — the for...in construct — is similar to Objective-C’s for...in construct. In Objective-C, this syntax is available whenever a class conforms to the NSFastEnumeration protocol. In Swift, it is available whenever a type adopts the SequenceType protocol.

In the for...in construct, the variable is implicitly declared with let on each iteration; it is thus immutable. It is also local to the block. On each iteration, a successive element of the sequence is used to initialize the variable, which is then in scope inside block. This is the form of for loop you’ll use most often, especially because it is so easy in Swift to create a sequence on the fly if you don’t have one already. In C, for example, the way to iterate through the numbers 1 to 5 is to use the second form, and you can certainly do the same in Swift:

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

println(i)

}

But in Swift, you can create a sequence of the numbers 1 through 5 on the fly — a Range — and that’s what you’ll usually do:

for i in 1...5 {

println(i)

}

A SequenceType has a generate method which yields a “generator” object which, itself, has a mutating next method that returns the next object in the sequence wrapped in an Optional, or nil if there is no next object. Under the hood, therefore, for...in is actually a kind of while loop:

var g = (1...5).generate()

while let i = g.next() {

println(i)

}

Sometimes you may find that writing out the while loop explicitly in that way makes the loop easier to control and to customize.

TIP

You can also make your own object type adopt SequenceType; in that case, it, too, can be enumerated with for...in. This will rarely be necessary, however, and explaining how to do it is outside the scope of this discussion.

The sequence will often be an existing value. It might be a String, in which case the variable values are the successive Characters. It might be an array, in which case the variable values are the successive elements of the array. It might be a dictionary, in which case the variable values are a key–value tuple, and you will probably express the variable as a tuple of two names in order to capture them. Many examples have already appeared in earlier chapters.

As I explained in Chapter 4, an array coming from Cocoa will usually need its elements cast down from AnyObject. It is quite typical to do this as part of the sequence specification:

for v in self.boardView.subviews as [UIView] {

v.removeFromSuperview()

}

The global enumerate method takes a sequence and yields a sequence of tuples preceding each element of the original sequence with its index number:

for (i,v) in enumerate(self.tiles) {

v.center = self.centers[i]

}

If the desired sequence is not a simple iteration — if, for example, you need to count backwards, or if you need to skip some values — you have two choices. One is to generate the sequence by calling the global stride function. It has two forms:

§ stride(from:through:by:)

§ stride(from:to:by:)

Which form you use depends on whether you want the sequence to include the final value or not. The by: argument can be negative:

for i in stride(from: 10, through: 0, by: -2) {

println(i) // 10, 8, 6, 4, 2, 0

}

The other possibility is to feed a sequence to the global lazy function. Now you have something called a LazyRandomAccessCollection to which you can apply map, filter, and reverse instance methods, thus modifying the original sequence:

let range = lazy(0...10).reverse().filter{$0 % 2 == 0}

for i in range {

println(i) // 10, 8, 6, 4, 2, 0

}

You can cycle through two sequences simultaneously using the global zip function, which takes two sequences and yields a Zip2 struct, which is itself a sequence. The value on each iteration through a Zip2 is a tuple of the corresponding elements from both original sequences; if one of the original sequences is longer than the other, the extra elements are ignored:

let arr1 = ["CA", "MD", "NY", "AZ"]

let arr2 = ["California", "Maryland", "New York"]

var d = [String:String]()

for (s1,s2) in zip(arr1,arr2) {

d[s1] = s2

} // now d is ["MD": "Maryland", "NY": "New York", "CA": "California"]

The second form of for loop is a clone of the C for loop (refer to Example 5-4). The idea here is usually to increment or decrement a counter. The before-all statement is executed once as the for loop is first encountered and is usually used for initialization of the counter. The condition is then tested, and if true, the block is executed; the condition will usually test whether the counter has reached some limit. The after-each statement is then executed, and will usually increment or decrement the counter; the condition is then immediately tested again. Thus, to execute a block using integer values 1, 2, 3, 4, and 5 for i, the standard formula (if you’re going to use this kind of for loop) is:

var i : Int

for i = 1; i < 6; i++ {

println(i)

}

To limit the scope of the counter to the inside of the curly braces, declare it as part of the before-all statement:

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

println(i)

}

No law says that this kind of for loop must be about counting or incrementing. Recall this earlier example of a while loop, where we cycle up the view hierarchy looking for a table view cell:

var v : UIView = textField

do { v = v.superview! } while !(v is UITableViewCell)

Here’s another way to express that, using a for loop whose block is empty:

var v : UIView

for v = textField; !(v is UITableViewCell); v = v.superview! {}

As in C, each statement in the declaration (separated by semicolon) may consist, itself, of more than one code statement (separated by comma). This can be a handy, elegant way to clarify your intentions. In this example from my own code, I declare two variables in the before-allstatement, and change both of them in the after-each statement; there are other ways to accomplish this same end, certainly, but this seems cleanest and clearest:

var values = [0.0]

for (var i = 20, direction = 1.0; i < 60; i += 5, direction *= -1) {

values.append( direction * M_PI / Double(i) )

}

Jumping

The Swift language has no provision for full-fledged jumping from one location in code to another; there is no goto command (notoriously “considered harmful”). The Swift modes of jumping are all effectively ways of shortcircuiting the flow of branch and loop constructs:

fallthrough

A fallthrough statement in a switch case aborts execution of the current case code and immediately begins executing the code of the next case. There must be a next case or the compiler will stop you.

continue

A continue statement in a loop construct aborts execution of the current iteration and proceeds to the next iteration:

§ In a while loop, continue means to perform immediately the conditional test.

§ In a for loop of the first type (for...in), continue means to proceed immediately to the next iteration if there is one.

§ In a for loop of the second type (C for loop), continue means to perform immediately the after-each statement and then the conditional test.

break

A break statement aborts the current construct:

§ In a loop, break aborts the loop completely.

§ In the code of a switch case, break aborts the entire switch construct.

When constructs are nested, you may need to specify which construct you want to continue or break. Therefore, Swift permits you to put a label before the start of a switch statement, a while loop, or a for loop. The label is an arbitrary name followed by a colon. You can then use that label name as a second term in a continue or break statement within the labeled construct at any depth, to specify that this is the construct you are referring to. That will probably cover any real-life situation where you would have wished for a goto.

Here’s an artifical example to illustrate the syntax. First, I’ll nest two for loops with no label:

for i in 1...5 {

for j in 1...5 {

println("\(i), \(j);")

break

}

}

// 1, 1; 2, 1; 3, 1; 4, 1; 5, 1;

As you can see from the output, that code keeps aborting the inner loop after one iteration, while the outer loop proceeds normally through all five iterations. But what if you wanted to abort the entire nested construct? The solution is a label:

outer: for i in 1...5 {

for j in 1...5 {

println("\(i), \(j);")

break outer

}

}

// 1, 1;

Aborting

Aborting is an extreme form of flow control; the program stops dead in its tracks. In effect, you have deliberately crashed your own program. This is an unusual thing to do, but it can be useful as a way of raising a very red flag: you don’t really want to abort, so that if you do abort, things must be so bad that you’ve no choice.

One way to abort is by calling the global function fatalError. It takes a String parameter permitting you to provide a message to appear in the console. I’ve already given this example:

required init(coder aDecoder: NSCoder) {

fatalError("init(coder:) has not been implemented")

}

That code says, in effect, that execution should never reach this point. We have no real implementation of init(coder:), and we do not expect to be initialized this way. If we are initialized this way, something has gone very wrong, and we want to crash, because our program has a serious bug.

An initializer containing a fatalError call does not have to initialize any properties. This is because fatalError is declared with the @noreturn attribute, which causes to the compiler to abandon any contextual requirements. Similarly, a function that returns a value does not have to return any value if a fatalError call is encountered.

You can also abort conditionally by calling the assert function. Its first parameter is a condition — something that evaluates as a Bool. If the condition is false, we will abort; the second parameter is a String message to appear in the console if we do abort. The idea here is that you are making a bet (an assertion) that the condition is true — a bet that you feel so strongly about that if the condition is false, there’s a serious bug in your program and you want to crash so you can learn of this bug and fix it.

By default, assert works only when you’re developing your program. When your program is to be finalized and made public, you throw a different build switch, telling the compiler that assert should be ignored. In effect, the conditions in your assert calls are then disregarded; they are all seen as true. This means that you can safely leave assert calls in your code. By the time your program ships, of course, none of your assertions should be failing in any case; any bugs that caused them to fail should already have been ironed out.

The disabling of assertions in shipping code is performed in an interesting way. The condition parameter is given an extra layer of indirection by declaring it as an @autoclosure function. This means that, even though the parameter is not in fact a function, the compiler will wrap it in a function; thus, the runtime needn’t call that function unless it has to. In shipping code, the runtime will not call that function. This mechanism averts expensive and unnecessary evaluation: an assert condition test may involve side effects, but the test won’t even be performed when assertions are turned off in your shipping program.

Operators

Swift operators such as + and > are not magically baked into the language. They are, in fact, functions; they are explicitly declared and implemented just like any other function. That is why, as I pointed out in Chapter 4, the term + can be passed as the last parameter in a reduce call;reduce expects a function taking two parameters and returning a value whose type matches that of the first parameter, and + is in fact the name of such a function. It also explains how Swift operators can be overloaded for different value types. You can use + with numbers, strings, or arrays — with a different meaning in each case — because two functions with the same name but different parameter types (different signatures) are two different functions; from the parameter types, Swift is able to determine which + function you are calling.

These facts are not merely an intriguing behind-the-scenes implementation detail. They have practical implications for you and your code. You are free to overload existing operators to apply to your object types. You can even invent new operators! In this section, we’ll do both.

First, we must talk about how operators are declared. Clearly there is some sort of syntactical hanky-panky (a technical computer science term), because you don’t call an operator function in the same way as a normal function. You don’t say +(1,2); you say 1+2. Even so, 1 and 2 in that second expression are the parameters to a + function call. How does Swift know that the + function uses this special syntax?

To see the answer, look in the Swift header:

infix operator + {

associativity left

precedence 140

}

That is an operator declaration. An operator declaration announces that this symbol is an operator, and tells how many parameters it has and what the usage syntax will be in relation to those parameters. The really important part is the stuff before the curly braces: the keyword operator, preceded by an operator type — here, infix — and followed by the name of the operator. The types are:

infix

This operator takes two parameters and appears between them.

prefix

This operator takes one parameter and appears before it.

postfix

This operator takes one parameter and appears after it.

An operator is also a function, so you also need a function declaration stating the type of the parameters and the result type of the function. Again, the Swift header shows us an example:

func +(lhs: Int, rhs: Int) -> Int

That is one of many declarations for the + function in the Swift header. In particular, it is the declaration for when the parameters are both Int. In that situation, the result is itself an Int. (The local parameter names lhs and rhs, which don’t affect the calling syntax, presumably mean “left-hand side” and “right-hand side.”)

Both an operator declaration and its corresponding function declaration(s) must appear at top level. If the operator is a prefix or postfix operator, the function declaration must start with the word prefix or postfix; the default is infix and can therefore be omitted.

We now know enough to override an operator to work with an object type of our own! As a simple example, imagine a Vial full of bacteria:

struct Vial {

var numberOfBacteria : Int

init(_ n:Int) {

self.numberOfBacteria = n

}

}

When two Vials are combined, you get a Vial with all the bacteria from both of them. So the way to add two Vials is to add their bacteria:

func +(lhs:Vial, rhs:Vial) -> Vial {

let total = lhs.numberOfBacteria + rhs.numberOfBacteria

return Vial(total)

}

And here’s code to test our new + operator override:

let v1 = Vial(500_000)

let v2 = Vial(400_000)

let v3 = v1 + v2

println(v3.numberOfBacteria) // 900000

In the case of a compound assignment operator, the first parameter is the thing being assigned to. Therefore, to implement such an operator, the first parameter must be declared inout. Let’s do that for our Vial class:

func +=(inout lhs:Vial, rhs:Vial) {

let total = lhs.numberOfBacteria + rhs.numberOfBacteria

lhs.numberOfBacteria = total

}

Here’s code to test our += override; Vial is a struct, so the first operand must be a mutable reference:

var v1 = Vial(500_000)

let v2 = Vial(400_000)

v1 += v2

println(v1.numberOfBacteria) // 900000

It might be useful also to override the equality comparison operator == for our Vial class. This satisfies the requirement for Vial to adopt the Equatable protocol, but of course it won’t actually adopt it unless we tell it to:

func ==(lhs:Vial, rhs:Vial) -> Bool {

return lhs.numberOfBacteria == rhs.numberOfBacteria

}

extension Vial:Equatable{}

Now that Vial is an Equatable, it becomes a candidate for use with global functions such as find:

let v1 = Vial(500_000)

let v2 = Vial(400_000)

let arr = [v1,v2]

let ix = find(arr,v1) // Optional wrapping 0

What’s more, the complementary inequality operator != has sprung to life for Vials automatically! That’s because it’s already defined for any Equatable in terms of the == operator. By the same token, if we now override < for Vial and tell it to adopt Comparable, the other three comparison operators spring to life automatically.

Next, let’s implement a completely new operator. As an example, I’ll inject an operator into Int that raises one number to the power of another. As my operator symbol, I’ll use ^^ (I’d like to use ^ but it’s already in use for something else). For simplicity, I’ll omit error-checking for edge cases (such as exponents less than 1):

infix operator ^^ {

}

func ^^(lhs:Int, rhs:Int) -> Int {

var result = lhs

for _ in 1..<rhs {result *= lhs}

return result

}

That’s all it takes! Here’s some code to test it:

println(2^^2) // 4

println(2^^3) // 8

println(3^^3) // 27

When defining an operator, you’ll add precedence and associativity specifications if you’re concerned about how this operator interacts in expressions containing other operators. I’m not going to go into the details; see the Swift manual if you need to. The manual also lists the special characters that can be used as part of a custom operator name:

/ = - + ! * % < > & | ^ ? ~

An operator name can also contain many other symbol characters (that is, characters that can’t be mistaken for some sort of alphanumeric) that are harder to type; see the manual for a formal list.

Privacy

Privacy (also known as access control) refers to the explicit modification of the normal scope rules. I gave an example in Chapter 1:

class Dog {

var name = ""

private var whatADogSays = "woof"

func bark() {

println(self.whatADogSays)

}

func speak() {

println(self.whatADogSays)

}

}

The intention here is to limit how other objects can see the Dog property whatADogSays. It is a private property, intended primarily for the Dog class’s own internal use: a Dog can speak of self.whatADogSays, but other objects should not be aware that it even exists.

Swift has three levels of privacy:

internal

The default rule is that declarations are internal, meaning that they are globally visible to all code in all files within the containing module. That is why Swift files within the same module can see one another’s top-level contents automatically, with no effort on your part. (That’s different from C and Objective-C, where files can’t see each other at all unless you explicitly show them to one another through include or import statements.)

private (narrower than internal)

A thing declared private is visible only within its containing file. The formulation of this rule may not be quite what you were expecting from the notion of privacy. In some languages, private means private to an object declaration. In Swift, private is not as private as that; two classes in the same file can see one another even if both are declared private. This could be a good reason for breaking your code into multiple files, following the usual convention of one class per file.

public (wider than internal)

A thing declared public is visible even outside its containing module. Another module must first import this module before it can see anything at all. But once another module has imported this module, it still won’t be able to see anything in this module that hasn’t been explicitly declared public. If you don’t write any modules, you might never need to declare anything public. If you do write a module, you must declare something public, or your module is useless.

Private Declaration

By declaring object members private, you specify by inversion what the public API of this object is. Here’s an example from my own code:

class CancelableTimer: NSObject {

private var q = dispatch_queue_create("timer",nil)

private var timer : dispatch_source_t! = nil

private var firsttime = true

private var once : Bool

private var handler : () -> ()

init(once:Bool, handler:()->()) {

// ...

}

func startWithInterval(interval:Double) {

// ...

}

func cancel() {

// ...

}

}

The initializer init(once:handler:) and the startWithInterval: and cancel methods, which are not marked private, are this class’s public API. They say, “Please feel free to call me!” The properties, however, are all private; no other code (that is, no code outside this file) can see them, either to get them or to set them. They are purely for the internal use of the methods of this class. They maintain state, but it is not a state that any other code needs to know about.

Bear in mind that privacy can be restricted only to the level of the current file. For example:

class Cat {

private var secretName : String? = nil

}

class Dog {

func nameCat(cat:Cat) {

cat.secretName = "Lazybones"

}

}

Why is that code legal? I said that a Cat’s secretName was private, so why is a Dog allowed to come along and change it? It’s because privacy is not at the level of the individual object type; it’s at the level of the file. I’ve defined Cat and Dog in the same file, so they (if you’ll pardon the expression) can see one another’s private members.

It happens that a convenient real-life convention is to define each class in its own file. In fact, the file is very often named after the class that’s defined within it; a file containing the declaration for the ViewController class will typically be named ViewController.swift. But there is no rule governing any of that. File names are not meaningful in Swift, and Swift files within the same module can all see inside one another automatically, without being told one another’s names. File names are mostly a convenience for the programmer: in Xcode, I see a list of my program’s files, so it’s helpful, when I want to find the declaration for the ViewController class, to see the name ViewController.swift giving me a hint as to which file to look in.

The formal reason for dividing your code into files is to make privacy work. Let’s say I have two files, Cat.swift and Dog.swift:

// Cat.swift:

class Cat {

private var secretName : String? = nil

}

// Dog.swift:

class Dog {

func nameCat(cat:Cat) {

cat.secretName = "Lazybones" // compile error

}

}

Now that code won’t compile: the compiler says, “Cat does not have a member named secretName.” Cat does have a member named secretName, but not as far as code in a different file is concerned. And Dog now is in a different file, so privacy works.

It may be that on some occasions you will want to draw a distinction between the privacy of a variable regarding setting and its privacy regarding getting. To draw this distinction, put the word get or set in parentheses after the privacy declaration to which it applies. Here’s an example from my code:

private(set) var bitmapContext : CGContext! = nil

That says: the setting of this variable is restricted to code within this same file. It says nothing about restricting the getting of this variable; other code in other files in this module can read this variable, but cannot write to it. (You can use this same syntax with a subscript function.)

Public Declaration

If you write a module, you’ll need to specify at least some object declarations as public, or code that imports your module won’t be able to see it. Other declarations that are not declared public are internal, meaning that they are private to the module. Thus, judicious use of publicdeclarations configures the public API of your module.

For example, in my Zotz app, which is a card game, the object types for creating and portraying cards and for combining them into a deck are bundled into a framework called ZotzDeck. Many of these types, such as Card and Deck, are declared public. Many utility object types, however, are not; the classes within the ZotzDeck module can see and use them, but code outside the module doesn’t need to be aware of them at all. For instance, to create a card, I have a factory class, CardFactory; it is not public, because a Deck of Cards comes into the hands of other code full-blown when Deck is initialized — the fact that a CardFactory class was used to assist in the process is a private implementation detail.

The members of a public object type are not, themselves, automatically public. If you want a method to be public, you have to declare it public. This is an excellent default behavior, because it means that these members are not shared outside the module unless you want them to be. (As Apple puts it, you must “opt in to publishing” object members.) For example, in the ZotzDeck module, the Card class is declared public but its initializer is not. Why? Because it doesn’t need to be. The way you (meaning the importer of the ZotzDeck module) get cards is by initializing a Deck; the initializer for Deck is declared public, so you can do that. There is never any reason to make a card independently of a Deck, and thanks to the privacy rules, you can’t.

Privacy Rules

It took time for Apple to add access control to Swift in the early months of the language’s release, mostly because the compiler had to be taught an extensive set of rules for ensuring that the privacy level of related things is coherent. For example:

§ A variable can’t be public if its type is private, because other code wouldn’t be able to use such a variable.

§ A public protocol’s members must be declared public when they are implemented by an adopter.

§ A subclass can’t be public unless the superclass is public.

§ A subclass can change an overridden member’s access level, but it cannot even see its superclass’s private members unless they are declared in the same file together.

And so on. I could proceed to list all the rules, but I won’t. There is no need for me to enunciate them formally. They are spelled out in great detail in the Swift manual, which you can consult if you need to. In general, you probably won’t need to; they make intuitive sense, and you can rely on the compiler to help you with useful error messages if you violate one.

For example, recall this code from Chapter 4:

extension CGAffineTransform : Printable {

public var description : String {

return NSStringFromCGAffineTransform(self)

}

}

Why do I declare description public? Because if I don’t, my code won’t compile. I’m extending a Cocoa type to adopt a Swift protocol. Swift and Cocoa are two different modules; their types are all public. I must declare this property public to carry it across the barrier between them, in accordance with the rule that a public protocol’s members must be declared public by the adopter.

Introspection

Swift provides limited ability to introspect an object — that is, to see the names and values of its properties. The Xcode debugger takes advantage of this to summarize an object in the Debug pane. In general, you probably won’t need to introspect any values directly; but this feature could be useful, for example, as a shortcut in implementing description.

To introspect an object, pass it through the global reflect function. This returns a new object typed with the MirrorType protocol, which can be examined like an array: it has a count property and Int subscripts, each of which yields a tuple of a name and a MirrorType value. A MirrorType also has a summary string property, suitable for printing in the console.

Here, for example, is the implementation of a Dog class with a simple description property that takes advantage of introspection. Instead of hard-coding a list of the class’s instance properties, we introspect the instance to obtain the names and values of the properties. This means that we can later add more properties without having to modify our description implementation:

struct Dog : Printable {

var name = "Fido"

var license = 1

var description : String {

var desc = "Dog:\n"

var properties = reflect(self)

for ix in 0 ..< properties.count {

let (s,m) = properties[ix]

desc.extend(s); desc.extend(" : ")

desc.extend(m.summary); desc.extend("\n")

}

return desc

}

}

If we now instantiate Dog and pass that instance to println, this is what we see in the console:

Dog:

name : Fido

license : 1

Memory Management

Swift memory management is handled automatically, and you will usually be unaware of it. Objects come into existence when they are instantiated and go out of existence as soon as they are no longer needed. Memory management of reference type objects, however, is quite tricky under the hood; I’ll devote Chapter 12 to a discussion of the underlying mechanism. Even for the Swift user, things can occasionally go wrong in this regard. (Value types do not require the sort of complex memory management that reference types do, so no memory management issues can arise for them.)

Trouble typically arises when two class instances have references to one another. When that’s the case, you can have a retain cycle which will result in a memory leak, meaning that the two instances never go out of existence. Some computer languages solve this sort of problem with a periodic “garbage collection” phase that detects retain cycles and cleans them up, but Swift doesn’t do that; you have to fend off retain cycles manually.

The way to test for and observe a memory leak is to implement a class’s deinit. This method is called when the instance goes out of existence. If the instance never goes out of existence, deinit is never called. That’s a bad sign, if you were expecting that the instance should go out of existence.

Here’s an example. First, I’ll make two class instances and watch them go out of existence:

func testRetainCycle() {

class Dog {

deinit {

println("farewell from Dog")

}

}

class Cat {

deinit {

println("farewell from Cat")

}

}

let d = Dog()

let c = Cat()

}

testRetainCycle() // farewell from Cat, farewell from Dog

When we run that code, both “farewell” messages appear in the console. We created a Dog instance and a Cat instance, but the only references to them are automatic (local) variables inside the testRetainCycle function. When execution of that function’s body comes to an end, all automatic variables are destroyed; that is what it means to be an automatic variable. There are no other references to our Dog and Cat instances that might make them persist, and so they are destroyed in good order.

Now I’ll change that code by giving the Dog and Cat objects references to each other:

func testRetainCycle() {

class Dog {

var cat : Cat? = nil

deinit {

println("farewell from Dog")

}

}

class Cat {

var dog : Dog? = nil

deinit {

println("farewell from Cat")

}

}

let d = Dog()

let c = Cat()

d.cat = c // create a...

c.dog = d // ...retain cycle

}

testRetainCycle() // nothing in console

When we run that code, neither “farewell” message appears in the console. The Dog and Cat objects have references to one another. Those are persisting references (also called strong references). A persisting reference sees to it that, for example, as long as our Dog has a reference to a particular Cat, that Cat will not be destroyed. That’s a good thing, and is a fundamental principle of sensible memory management. The bad thing is that the Dog and the Cat have persisting references to one another. That’s a retain cycle! Neither the Dog instance nor the Cat instance can be destroyed, because neither of them can “go first” — it’s like Alphonse and Gaston who can never get through the door because each requires the other to precede him. The Dog can’t be destroyed first because the Cat has a persisting reference to him, and the Cat can’t be destroyed first because the Dog has a persisting reference to him.

These objects are therefore now leaking. Our code is over; both d and c are gone. There are no further references to either of these objects; neither object can ever be referred to again. No code can mention them; no code can reach them. But they live on, floating, useless, and taking up memory.

Weak References

One solution to a retain cycle is to mark the problematic reference as weak. This means that the reference is not a persisting reference. It is a weak reference. The object referred to can now go out of existence even while the referrer continues to exist. Of course, this presents a terrible danger, because now the object referred to may be destroyed behind the referrer’s back. But Swift has a solution for that, too: only an Optional reference can be marked as weak. That way, if the object referred to is destroyed behind the referrer’s back, the referrer will see something coherent, namelynil. Also, the reference must be a var reference, precisely because it can change spontaneously to nil.

Thus, this code breaks the retain cycle and prevents the memory leak:

func testRetainCycle() {

class Dog {

weak var cat : Cat? = nil

deinit {

println("farewell from Dog")

}

}

class Cat {

weak var dog : Dog? = nil

deinit {

println("farewell from Cat")

}

}

let d = Dog()

let c = Cat()

d.cat = c

c.dog = d

}

testRetainCycle() // farewell from Cat, farewell from Dog

I’ve gone overboard in that code. To break the retain cycle, there’s no need to make both Dog’s cat and Cat’s dog weak references; making just one of the two a weak reference is sufficient to break the cycle. That, in fact, is the usual solution when a retain cycle threatens. One of the pair will be more of an “owner” than the other; the one that is not the “owner” will have a weak reference to its “owner.”

Although, as I mentioned earlier, value types are not subject to the same memory management issues as reference types, a struct instance (which is a value type) can still be involved in a retain cycle with a class instance. In my retain cycle example, if Dog is a class and Cat is a struct, we still get a retain cycle. The solution is the same: make Cat’s dog a weak reference. (You can’t make Dog’s cat a weak reference, because Cat is a struct, and only references to a class type can be declared weak.)

Do not use weak references unless you have to! Memory management is not to be toyed with lightly. Nevertheless, there are real-life situations in which weak references are the right thing to do, even when no retain cycle appears to threaten. For example, a view controller’s references tosubviews of its own view are usually weak, because the view itself already has persisting references to those subviews, and we would not typically want those subviews to persist in the absence of the view itself:

class HelpViewController: UIViewController {

weak var wv : UIWebView? = nil

override func viewWillAppear(animated: Bool) {

super.viewWillAppear(animated)

let wv = UIWebView(frame:self.view.bounds)

// ... further configuration of wv here ...

self.view.addSubview(wv)

self.wv = wv

}

// ...

}

In that code, self.view.addSubview(wv) causes the UIWebView wv to persist; our own reference to it, self.wv, can thus be weak.

Unowned References

There’s another Swift solution for retain cycles. Instead of marking a reference as weak, you can mark it as unowned. This approach is useful in special cases where one object absolutely cannot exist without a reference to another, but where this reference need not be a persisting reference.

For example, let’s pretend that a Boy may or may not have a Dog, but every Dog must have a Boy — and so I’ll give Dog an init(boy:) initializer. The Dog needs a reference to its Boy, and the Boy needs a reference to his Dog if he has one; that’s potentially a retain cycle:

func testUnowned() {

class Boy {

var dog : Dog? = nil

deinit {

println("farewell from Boy")

}

}

class Dog {

let boy : Boy

init(boy:Boy) { self.boy = boy }

deinit {

println("farewell from Dog")

}

}

let b = Boy()

let d = Dog(boy: b)

b.dog = d

}

testUnowned() // nothing in console

We can solve this by declaring Dog’s boy property unowned:

func testUnowned() {

class Boy {

var dog : Dog? = nil

deinit {

println("farewell from Boy")

}

}

class Dog {

unowned let boy : Boy // *

init(boy:Boy) { self.boy = boy }

deinit {

println("farewell from Dog")

}

}

let b = Boy()

let d = Dog(boy: b)

b.dog = d

}

testUnowned() // farewell from Boy, farewell from Dog

An advantage of an unowned reference is that it doesn’t have to be an Optional — in fact, it cannot be an Optional — and it can be a constant (let). But an unowned reference is also dangerous, because the object referred to can go out of existence behind the referrer’s back, and an attempt to use that reference will cause a crash, as I can demonstrate by this rather forced code:

var b = Optional(Boy())

let d = Dog(boy: b!)

b = nil // destroy the Boy behind the Dog's back

println(d.boy) // crash

Thus, you should use unowned only if you are absolutely certain that the object referred to will outlive the referrer.

Weak and Unowned References in Anonymous Functions

A subtle variant of a retain cycle arises when an instance property’s value is a function referring to the instance:

class FunctionHolder {

var function : (Void -> Void)? = nil

deinit {

println("farewell from FunctionHolder")

}

}

func testFunctionHolder() {

let f = FunctionHolder()

f.function = {

println(f)

}

}

testFunctionHolder() // nothing in console

Oooops! I’ve created a retain cycle, by referring, inside the anonymous function, to the object that is holding a reference to it. Because functions are closures, f is captured by the anonymous function as a persisting reference. But the function property of FunctionHolder is a persisting reference too, so that’s a retain cycle: f persistently refers to the function, which persistently refers to f.

In this situation, I cannot break the retain cycle by declaring the function property as weak or unowned. Only a reference to a class type can be declared weak or unowned, and a function is not a class. Thus, I must declare the captured value f inside the anonymous function as weak orunowned instead.

Swift provides an ingenious syntax for doing that. At the very start of the anonymous function body, where the in line would go (and before the in line if there is one), you put square brackets containing a comma-separated list of any problematic class type references that will be captured from the surrounding environment, each reference preceded by weak or unowned. This list is called a capture list. If you have a capture list, you must follow it by the keyword in if you are not already including the keyword in for other reasons. Thus:

class FunctionHolder {

var function : (Void -> Void)? = nil

deinit {

println("farewell from FunctionHolder")

}

}

func testFunctionHolder() {

let f = FunctionHolder()

f.function = {

[weak f] in

println(f)

}

}

testFunctionHolder() // farewell from FunctionHolder

This syntax solves the problem. But marking a reference as weak in a capture list has a mild side effect that you will need to be aware of: such a reference passes into the anonymous function as an Optional. This is good, because it means that nothing bad can happen: if the object referred to goes out of existence behind our back, the value of the Optional is nil. But of course you must also adjust your code accordingly, unwrapping the Optional as needed in order to use it. The usual technique is to perform the weak–strong dance: you unwrap the Optional once, right at the start of the function, in a conditional binding, thus creating a new scope in which there is a normal (non-Optional) reference. Everything else in the anonymous function is embedded in that scope:

class FunctionHolder {

var function : (Void -> Void)? = nil

deinit {

println("farewell from FunctionHolder")

}

}

func testFunctionHolder() {

let f = FunctionHolder()

f.function = { // here comes the weak–strong dance

[weak f] in // weak

if let f = f { // strong

println(f)

}

}

}

testFunctionHolder() // farewell from FunctionHolder

The conditional binding let f = f accomplishes two goals. First, it unwraps the Optional version of f that arrived into the anonymous function. Second, it is a normal (strong) reference. So if the unwrapping succeeds, this new f will persist for the rest of the embedded scope.

In that particular example, there is no way on earth that this FunctionHolder instance, f, can go out of existence while the anonymous function lives on. There are no other references to the anonymous function; it persists only as a property of f. Therefore I can avoid some behind-the-scenes bookkeeping overhead, as well as the weak–strong dance, by declaring f as unowned in my capture list instead.

In real life, my own most frequent use of unowned is precisely in this context. Very often, the reference marked as unowned in the capture list will be self. Here’s an example from my own code:

class MyDropBounceAndRollBehavior : UIDynamicBehavior {

let v : UIView

init(view v:UIView) {

self.v = v

super.init()

}

override func willMoveToAnimator(anim: UIDynamicAnimator!) {

if anim == nil { return }

let sup = self.v.superview!

let grav = UIGravityBehavior()

grav.action = {

[unowned self] in

let items = anim.itemsInRect(sup.bounds) as [UIView]

if find(items, self.v) == nil {

anim.removeBehavior(self)

self.v.removeFromSuperview()

}

}

self.addChildBehavior(grav)

grav.addItem(self.v)

// ...

}

// ...

}

There’s a potential (and rather elaborate) retain cycle here: self.addChildBehavior(grav) causes a persistent reference to grav, grav has a persistent reference to grav.action, and the anonymous function assigned to grav.action refers to self. To break the retain cycle, I declare the reference to self as unowned in the anonymous function’s capture list.

Memory Management of Protocol-Typed References

Only a reference to an instance of a class type can be declared weak or unowned. A reference to an instance of a struct or enum type cannot be so declared, because its memory management doesn’t work the same way (and is not subject to retain cycles).

A reference that is declared as a protocol type, therefore, has a problem. A protocol might be adopted by a struct or an enum. Therefore you cannot wantonly declare such a reference weak or unowned. You can only declare a protocol-typed reference weak or unowned if it is a class protocol — that is, if it is marked with @objc or class.

In this code, SecondViewControllerDelegate is a protocol that I’ve declared. This code won’t compile unless SecondViewControllerDelegate is declared as a class protocol:

class SecondViewController : UIViewController {

weak var delegate : SecondViewControllerDelegate?

// ...

}

Here’s the actual declaration of SecondViewControllerDelegate; it is declared as a class protocol, and that’s why the preceding code is legal:

protocol SecondViewControllerDelegate : class {

func acceptData(data:AnyObject!)

}

A protocol declared in Objective-C is implicitly marked as @objc and is a class protocol. Thus, this declaration from my real-life code is legal:

weak var delegate : WKScriptMessageHandler?

WKScriptMessageHandler is a protocol declared by Cocoa (in particular, by the Web Kit framework). Thus, it is implicitly marked @objc; only a class can adopt WKScriptMessageHandler, and so the compiler is satisfied that the delegate variable will be an instance of a class, and thus the reference can be treated as weak.