Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Swift Essentials
Swift Essentials

Swift Essentials: Get up and running lightning fast with this practical guide to building applications with Swift

Arrow left icon
Profile Icon Alex Blewitt Profile Icon Bandlem Limited
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.8 (4 Ratings)
Paperback Dec 2014 228 pages 1st Edition
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
Arrow left icon
Profile Icon Alex Blewitt Profile Icon Bandlem Limited
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.8 (4 Ratings)
Paperback Dec 2014 228 pages 1st Edition
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Swift Essentials

Chapter 1. Exploring Swift

Apple announced Swift at WWDC 2014 as a new programming language that combines experience with the Objective-C platform and advances in dynamic and statically typed languages over the last few decades. Before Swift, most code written for iOS and OS X applications was in Objective-C, a set of object-oriented extensions to the C programming language. Swift aims to build upon patterns and frameworks of Objective-C but with a more modern runtime and automatic memory management.

This chapter will present the following topics:

  • How to use the Swift REPL to evaluate Swift code
  • The different types of Swift literals
  • How to iterate through arrays, dictionaries, and sequences
  • Functions and the different types of function arguments
  • Compiling and running Swift from the command line

Getting started with Swift

Swift provides a runtime interpreter that executes statements and expressions. The Swift interpreter is called swift and can be launched from the Xcode 6 tools using the xcrun command in a Terminal.app shell:

$ xcrun swift
Welcome to Swift!  Type :help for assistance.
>

The xcrun command allows a toolchain command to be executed; in this case, it finds /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift. The swift command sits alongside other compilation tools such as clang and ld, and permits multiple versions of the commands and libraries to be installed on the same machine without conflicting. The Swift prompt displays > for new statements and . for continuation. Statements and expressions typed into the interpreter are evaluated and immediately displayed. Anonymous values are given references, so they can be used subsequently:

> "Hello " + 
. "World"
$R0: String = "Hello World"
> 3 + 4
$R1: Int = 7
> $R0
$R2: String = "Hello World"
> $R1
$R3: Int = 7

Numeric literals

Numeric types in Swift can represent both signed and unsigned integral values with sizes 8, 16, 32, or 64 bits, as well as signed 32 or 64 bit floating point values. Numbers can include underscores to provide better readability; so 68_040 is the same as 68040:

> 3.141
$R0: Double = 3.141
> 299_792_458
$R1: Int = 299792458
> -1
$R2: Int = -1
> 1_800_123456
$R3: Int = 1800123456

Numbers can also be written in binary, octal, or hexadecimal using prefixes 0b, 0o (zero and the letter "o") or 0x. Note that Swift does not inherit C's use of a leading zero (0) to represent an octal value, unlike Java and JavaScript which do. Examples include:

> 0b1010011
$R0: Int = 83
> 0o123
$R1: Int = 83
> 0123
$R2: Int = 123
> 0x7b
$R3: Int = 123

Floating point literals

There are three types of floating point values available in Swift, which use the IEEE754 floating point standard. The Double type represents 64 bits worth of data whilst Float stores 32 bits of data. In addition, Float80 is a specialized type that stores 80 bits worth of data.

Note

Some CPUs internally use 80 bit precision to perform math operations, and the Float80 type allows this accuracy to be used in Swift. Not all architectures support Float80 natively, so this should be used sparingly.

By default, floating point values in Swift have the Double type. As floating point representation cannot represent some numbers exactly, some values will be displayed with a rounding error; for example:

> 3.141
$R0: Double = 3.141
> Float(3.141)
$R1: Float = 3.1400003

Floating point values can be specified in decimal or hexadecimal. Decimal floating point uses e as the exponent for base 10, whereas hexadecimal floating point uses p as the exponent for base 2. A value of AeB has the value A*10^B and a value of 0xApB has the value A*2^B:

> 299.792458e6
$R0: Double = 299792458
> 299.792_458_e6
$R1: Double = 299792458
> 0x1p8
$R2: Double = 256
> 0x1p10
$R3: Double = 1024
> 0x4p10
$R4: Double = 4096
> 1e-1
$R5: Double = 0.10000000000000001
> 1e-2
$R6: Double = 0.01
> 0x1p-1
$R7: Double = 0.5
> 0x1p-2
$R8: Double = 0.25
> 0xAp-1
$R9: Double = 5

String literals

Strings can contain escaped characters, unicode characters, and interpolated expressions. Escaped characters use a slash (\) and can be one of:

  • \\ Literal slash \
  • \0 The null character
  • \' Literal single quote '
  • \" Literal double quote "
  • \t Tab
  • \n Line feed
  • \r Carriage return
  • \u{NNN} Unicode character such as the Euro symbol \u{20AC} or smiley \u{1F600}

An interpolated string has an embedded expression which is evaluated, converted into a string, and concatenated into the result. These interpolated strings can capture local variables or expressions:

> "3+4 is \(3+4)"
$R0: String = "3+4 is 7"
> 3+4
$R1: Int = 7
> "7 x 2 is \($R1 * 2)"
$R2: String = "7 x 2 is 14"

Note

Expressions in interpolated strings cannot contain double quotes. If the expression requires double quotes, assign the value to a constant first and then use that constant in the interpolated string.

Variables and constants

Swift distinguishes between variables (which can be modified) and constants (which cannot be changed after assignment). Identifiers start with an underscore or alphabetic letter, followed by an underscore or alphanumeric character. In addition, other Unicode character points (such as emoji) can be used, although box lines and arrows are not allowed. Consult the Swift language guide for the full set of allowable Unicode characters. Generally, private use areas are not allowed and identifiers cannot start with a combining character (such as an accent).

Variables are defined with the var keyword and constants are defined with the let keyword. If the types are not specified, they are automatically inferred:

> let pi = 3.141
pi: Double = 3.141
> pi = 3
error: cannot assign to 'let' value 'pi'
> var i = 0
i: Int = 0
> ++i
$R0: Int = 1

Types can be explicitly specified. For example, to store a 32 bit floating point value, the variable can be defined as a Float, or to store a value as an unsigned 8 bit integer, UInt8:

> let e:Float = 2.718
e: Float = 2.71799994
> let ff:UInt8 = 255
ff: UInt8 = 255

To convert a number to a different type, it can be converted using the type initializer or assigned to a variable of a different type, provided it does not underflow or overflow:

> let ooff = UInt16(ff)
ooff: UInt16 = 255
> Int8(255)
error: integer overflows when converted from 'Int' to 'Int8'
Int8(255)
^
> UInt8(Int8(-1))
error: negative integer cannot be converted to unsigned type 'UInt8'
UInt8(Int8(-1))
^

Collection types

Swift has two collection types: Array and Dictionary. They are strongly typed and generic, which ensures that the values of types assigned are compatible with the element type. The literal syntax for arrays uses [] to store a comma-separated list, while dictionaries use a comma-separated [key:value] format for entries. Collections defined with var are mutable; collections defined with let are immutable.

> var shopping = [ "Milk", "Eggs", "Coffee", ]
shopping: [String] = 3 values {
  [0] = "Milk"
  [1] = "Eggs"
  [2] = "Coffee"
}
> var costs = [ "Milk":1, "Eggs":2, "Coffee":3, ]
costs: [String : Int] = {
  [0] = { key = "Coffee" value = 3 }
  [1] = { key = "Milk"   value = 1 }
  [2] = { key = "Eggs"   value = 2 }
}

Note

For readability, array and dictionary literals can have a trailing comma. This allows initialization to be split over multiple lines, and if the last element ends with a trailing comma, adding new items does not result in an SCM diff to the previous line.

Arrays and dictionaries can be indexed using subscript operators, reassigned, and added to as follows:

> shopping[0]
$R0: String = "Milk"
> costs["Milk"]
$R1: Int? = 1
> shopping.count
$R2: Int = 3
> shopping += [ "Tea" ]
> shopping.count
$R3: Int = 4
> costs.count
$R4: Int = 3
> costs["Tea"] = "String"
error: '@lvalue $T5' is not identical to '(String, Int)'
> costs["Tea"] = 4
> costs.count
$R5: Int = 4

Optional types

In the previous example, the return type of costs["Milk"] is Int? and not Int. This is an optional type; it represents the possibility of an Int existing. For a dictionary of type T, the return type will be T?. If the value doesn't exist in the dictionary, then the returned value will be nil. Other object-oriented languages, such as Objective-C, C++, Java, and C#, have optional types by default; any object value (or pointer) can be null. By expressing optionality in the type system, Swift can determine whether a value really has to exist or might be nil:

> var cannotBeNil:Int = 1
cannotBeNil: Int = 1
> cannotBeNil = nil
error: type 'Int' does not conform to protocol 'NilLiteralConvertible'
cannotBeNil = nil
> var canBeNil:Int? = 1
canBeNil: Int? = 1
> canBeNil = nil
> canBeNil
$R0: Int? = nil

Note

Optional types can be explicitly created using the Optional constructor. Given a value x of type X, an optional X? value can be created using Optional(x).

The value can be tested against nil to find out whether it contains a value and then unpacked with opt!.

As an example, here is how to create and unwrap an optional value:

> var opt: Int? = 1
opt: Int? = 1
> opt == nil
$R1: Bool = false
> opt!
$R2: Int = 1

If a nil value is unpacked, an error occurs:

> opt = nil
> opt!
fatal error: unexpectedly found nil while unwrapping an Optional value
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)

Particularly when working with Objective-C based APIs, it is common for values to be declared as optional, although they are always expected to return a value. It is possible to declare such variables as implicitly unwrapped optionals; these variables behave as optional values (they may contain nil), but when the value is accessed, they are automatically unwrapped on demand:

> var implicitlyUnwrappedOptional:Int! = 1
implicitlyUnwrappedOptional: Int! = 1
> implicitlyUnwrappedOptional + 2
3
> implicitlyUnwrappedOptional = nil
> implicitlyUnwrappedOptional + 2
fatal error: unexpectedly found nil while unwrapping an Optional value

Tip

In general, implicitly unwrapped optionals should be avoided as they are likely to lead to errors. They are mainly useful for interaction with existing Objective-C APIs when the value is known to have an instance.

Nil coalescing operator

Swift has a nil coalescing operator, which is similar to Groovy's ?: operator or C#'s ?? operator. This provides a means to specify a default value if an expression is nil:

> 1 ?? 2
$R0: Int = 1
> nil ?? 2
$R1: Int = 2

The nil coalescing operator can also be used to unwrap an optional value. If the optional value is present, it is unwrapped and returned; if it is missing, then the right-hand side of the expression is returned. Like the shortcut || and && operators, the right-hand side is not evaluated unless necessary:

> costs["Tea"] ?? 0
$R2: Int = 4
> costs["Sugar"] ?? 0
$R3: Int = 0

Conditional logic

There are two key types of conditional logic in Swift (known as branch statements in the grammar): the if statement and the switch statement. Unlike other languages, the body of the if must be surrounded with braces {}, and if typed in at the interpreter, the opening brace { must be on the same line as the if statement. The literal values true and false can be used as well as other boolean expressions.

If statements

Conditionally unpacking an optional value is so common that a specific Swift pattern has been created to avoid evaluating the expression twice:

var shopping = [ "Milk", "Eggs", "Coffee", "Tea", ]
var costs = [ "Milk":1, "Eggs":2, "Coffee":3, "Tea":4, ]
var cost = 0
if let cm = costs["Milk"] {
.   cost += cm
. }
> cost
$R0: Int = 1

The if block only executes if the optional value exists. The definition of the constant cm only exists for the body of the if block, and does not exist outside that scope. Furthermore, cm is a non-optional type, so it is guaranteed to not be nil.

To execute an alternative block if the item cannot be found, an else block can be used:

> if let cb = costs["Bread"] {
.  cost += cb
. } else {
.  println("Cannot find any Bread")
. }
Cannot find any Bread

Other boolean expressions can include any expression that conforms to the BooleanType protocol, the equality operators == and !=, the identity operators === and !==, as well as the comparison operators <, <=, >, >=. The is type operator provides a test to see whether an element is of a particular type.

Note

The difference between the equality operator and the identity operator is relevant for classes or other reference types. The equality operator asks "Are these two values equivalent to each other?" whereas the identity operator asks "Are these two references equal to each other?"

There is a boolean operator specific to Swift, which is the ~= pattern match operator. Despite the name, this isn't anything to do with regular expressions; rather, it's a way of asking whether a pattern matches a particular value. This is used in the implementation of the switch block, which is covered in the next section.

In addition to the if statement, there is a ternary if expression similar to other languages. After a condition, a question mark (?) is used, followed by an expression to be used if the condition is true, then a colon (:) followed by the false expression:

> var i = 17
i: Int = 17
> i % 2 == 0 ? "Even" : "Odd"
$R0: String = "Odd"

Switch statements

In addition to if/else, Swift also has a switch statement, similar to C and Java's switch. However, it differs in two important ways. Firstly, case statements no longer have a default fall-through behavior (so there are no bugs introduced by missing a break statement) and secondly, the value of the case statements can be expressions instead of values, pattern matching on type and range. At the end of the corresponding case, the evaluation jumps to the end of the switch block, unless the fallthrough keyword is used. If no case statements match, the default statement is executed:

> var position = 21
position: Int = 21
> switch position {
.   case 1: println("First")
.   case 2: println("Second")
.   case 3: println("Third")
.   case 4...20: println("\(position)th")
.   case position where (position % 10) == 1:
.     println("\(position)st")
.   case let p where (p % 10) == 2:
.     println("\(p)nd")
.   case let p where (p % 10) == 3:
.     println("\(p)rd")
.   default: println("\(position)th")
. }
21st

In the preceding example, the expression prints out First, Second, or Third if the position is 1, 2, or 3 respectively. For numbers between 4 and 20 (inclusive), it prints out the position with a th ordinal. Otherwise, for numbers that end with 1, it prints st; for numbers that end with 2, it prints nd; and for numbers that end with 3, it prints rd. For all other numbers, it prints th.

The 4...20 range expression in a case statement represents a pattern. If the value of the expression matches that pattern, then the corresponding statements will be executed:

> 4...10 ~= 4
$R0: Bool = true
> 4...10 ~= 21
$R1: Bool = false

There are two range operators in Swift: an inclusive or closed range, and an exclusive or half-open range. The closed range is specified with three dots; 1...12 will give a list of integers between one and twelve. The half-open range is specified with two dots and a less than operator; so 1..<10 will provide integers from 1 to 9 but exclude 10.

The where clause in the switch block allows an arbitrary expression to be evaluated, provided that the pattern matches. These are evaluated in-order, in the sequence they are in the source file. If a where clause evaluates to true, then the corresponding set of statements will be executed.

The let variable syntax can be used to define a constant that refers to the value in the switch block. This local constant can be used in the where clause or the corresponding statements for that specific case. Alternatively, variables can be used from the surrounding scope.

Note

If multiple case statements need to match the same pattern, they can be separated with commas in the form of an expression list. Alternatively, the fallthrough keyword can be used to allow the same implementation to be used for multiple case statements.

Iteration

Ranges can be used to iterate a fixed number of times, for example, for i in 1...12. To print out these numbers, a loop such as the following can be used:

> for i in 1...12 {
.   println("i is \(i)")
. }

If the number is not required, then the underscore (_) can be used as a hole to act as a throwaway value. An underscore can be assigned to, but not read:

> for _ in 1...12 {
.   println("Looping...")
. }

However, it is more common to iterate over a collection's contents using a for...in pattern. This steps through each of the items in the collection, and the body of the for loop is executed over each one:

> var shopping = [ "Milk", "Eggs", "Coffee", "Tea", ]
> var costs = [ "Milk":1, "Eggs":2, "Coffee":3, "Tea":4, ]
> var cost = 0
> for item in shopping {
.  if let itemCost = costs[item] {
.   cost += itemCost
.  }
. }
> cost
cost: Int = 10

To iterate over a dictionary, it is possible to extract the keys or the values and process them as an array:

> Array(costs.keys)
$R2: [String] = 4 values {
  [0] = "Coffee"
  [1] = "Milk"
  [2] = "Eggs"
  [3] = "Tea"
}
> Array(costs.values)
$R3: [Int] = 4 values {
  [0] = 3
  [1] = 1
  [2] = 2
  [3] = 4
}

Note

Note that the order of keys in a dictionary are not guaranteed; if the dictionary changes size, the order may change.

Converting a dictionary's values to an array is not performant, as this will result in a copy of the data being made. Instead, the underlying values are of a type MapCollectionView, which provides an iterable internal view of the data structure:

> costs.keys
$R4: LazyBidirectionalCollectionMapCollectionView<[String : Int], String>> = {
  _base = {
    _base = {
      [0] = { key = "Coffee" value = 3 }
      [1] = { key = "Milk"   value = 1 }
      [2] = { key = "Eggs"   value = 2 }
      [3] = { key = "Tea"    value = 4 }
    }
  _transform =
  }
}

To print out all the keys in a dictionary, the keys property can be used with a for...in loop:

> for item in costs.keys {
. println(item)
. }
Coffee
Milk
Eggs
Tea

Iterating over keys and values in a dictionary

Traversing a dictionary to obtain all of the keys and then subsequently looking up values will result in searching the data structure twice. Instead, both the key and the value can be iterated at the same time using a tuple. A tuple is like a fixed-sized array, but one that allows assigning pairs (or triplets and so on) of values at a time:

> var (a,b) = (1,2)
a: Int = 1
b: Int = 2

Tuples can be used to iterate pairwise over both the keys and values of a dictionary:

> for (item,cost) in costs {
.  println("The \(item) costs \(cost)")
. }
The Coffee costs 3
The Milk costs 1
The Eggs costs 2
The Tea costs 4

Both Array and Dictionary conform to the SequenceType protocol, which allows them to be iterated with a for...in loop. Collections (as well as other objects such as Range) that implement SequenceType have a generate method, which returns a GeneratorType that allows the data to be iterated over. It is possible for custom Swift objects to implement SequenceType to allow them to be used in a for...in loop.

Iteration with for loops

Although the most common use of the for operator in Swift is in a for...in loop, it is also possible to use a more traditional form of for loop. This has an initialization, a condition that is tested at the start of each loop, and a step operation that is evaluated at the end of each loop. Although the parentheses around the for loop are optional, the braces for the block of code are mandatory.

Calculating the sum of integers between 1 and 10 without using the range operator can be done as follows:

> var sum = 0
. for var i=0; i<=10; ++i {
.  sum += i
. }
sum: Int = 55

If multiple variables need to be updated in the for loop, Swift has an expression list that is a set of comma-separated expressions. To step through two sets of variables in a for loop, the following can be used:

> for var i = 0,j = 10; i<=10 && j >= 0; ++i,--j { 
.  println("\(i), \(j)") 
. } 
0, 10
1, 9
…
9, 1
10, 0

Tip

Apple recommends the use of ++i instead of i++ (and conversely, --i instead of i--) because they will return the result of i after the operation, which may be the expected value.

Break and continue

The break statement leaves the innermost loop early, and control jumps to the end of the loop. The continue statement takes execution to the top of the innermost loop and the next item.

To break or continue from nested loops, a label can be used. Labels in Swift can only be applied to a loop statement such as while or for. A label is introduced by an identifier and a colon just before the loop statement:

> var deck = [1...13, 1...13, 1...13, 1...13]
> suits: for suit in deck { 
.  for card in suit { 
.   if card == 3 {
.    continue // go to next card in same suit
.   }
.   if card == 5 { 
.     continue suits // go to next suit
.   } 
.   if card == 7 {
.     break // leave card loop
.   }
.   if card == 13 {
.     break suits // leave suit loop
.   }
.  } 
. }     

Functions

Functions can be created using the func keyword, which takes a set of arguments and a body that can be invoked. The return statement can be used to leave a function:

> var shopping = [ "Milk", "Eggs", "Coffee", "Tea", ]
> var costs = [ "Milk":1, "Eggs":2, "Coffee":3, "Tea":4, ]
> func costOf(items:[String], costs:[String:Int]) -> Int {
.   var cost = 0
.   for item in items {
.    if let cm = costs[item] {
.     cost += cm
.    }
.   }
.   return cost
. }
> costOf(shopping,costs)
$R0: Int = 10

The return type of the function is specified after the arguments with an arrow (->). If missing, the function cannot return a value; if present, the function must return a value of that type.

Functions with positional arguments can be called with parentheses, such as the costOf(shopping,costs) call. If a function takes no arguments, then the parentheses are still required.

Note

The foo() expression calls the function foo with no arguments. The expression foo is the function itself, so an expression such as let copyOfFoo = foo results in a copy of the function; so copyOfFoo() and foo() have the same effect.

Named arguments

Swift also supports named arguments, which can either use the name of the variable or can be defined with an external parameter name. To modify the function to support calling with basket and prices as argument names, the following can be done:

> func costOf(basket items:[String], prices costs:[String:Int]) -> Int {
.   var cost = 0
.   for item in items {
.    if let cm = costs[item] {
.     cost += cm
.    }
.   }
.   return cost
. }
> costOf(basket:shopping, prices:costs)
$R1: Int = 10

This example defines external parameter names basket and prices for the function. The function signature is often referred to as costOf(basket:prices:) and is useful when it may not be clear what the arguments are for (particularly if they are for the same type).

A shorthand is available to use the same external name as the parameter name, by prefixing it with a hash (#). These are called shorthand external parameter names:

> func costOf(#items:[String], #costs:[String:Int]) -> Int {
. var cost = 0
. for item in items {
.  if let cm = costs[item] {
.   cost += cm
.  }
. }
. return cost
. }
> costOf(items:shopping, costs:costs)
$R2: Int = 10

Refactoring shorthand external parameter names will lead to API breakage. If it is necessary to change the name internally in a function, convert it from a shorthand name to a separate external and internal parameter name.

Optional arguments and default values

Swift functions can have optional arguments by specifying default values in the function definition. When the function is called and an optional argument is missing, the default value for that argument is used.

Note

Note that an optional argument is one that can be omitted in the function call, rather than a required argument that takes an optional value. This naming is unfortunate. It may help to think of these as default arguments rather than optional arguments.

A default parameter value is specified after the type in the function signature, with an equal sign (=) and then the expression. The expression is re-evaluated each time the function is called without a corresponding value. Default arguments are implicitly named so that the hash (indicating a named argument) is superfluous and will generate warnings.

In the costOf example, instead of passing the value of costs each time, it could be defined with a default parameter as follows:

> func costOf(#items:[String], costs:[String:Int] = costs) -> Int {
.   var cost = 0
.   for item in items {
.    if let cm = costs[item] {
.     cost += cm
.    }
.   }
.   return cost
. }
> costOf(items:shopping)
$R3: Int = 10
> costOf(items:shopping, costs:costs)
$R4: Int = 10

Note that in the first expression, the captured costs variable is bound when the function is defined. If costs is re-assigned at a later stage, then the function will not be updated.

Anonymous arguments

Swift requires that arguments with default values are named, as are arguments that are used in initializers for classes (which are covered in the Classes in Swift section in Chapter 3, Creating an iOS Swift App).

In some cases, this is unnecessary or unhelpful. To disable requiring a named argument for a parameter, the special value underscore (_) can be used:

> func costOf(items:[String], _ costs:[String:Int] = costs) -> Int {
.   var cost = 0
.   for item in items {
.     if let cm = costs[item] {
.       cost += cm
.     }
.   }
.   return cost
. }
> costOf(shopping)
$R0: Int = 10
> costOf(shopping,costs)
$R1: Int = 10

Multiple return values and arguments

So far, the examples of functions have all returned a single type. What happens if there is more than one return result from a function? In an object-oriented language, the answer is to return a class; however, Swift has tuples, which can be used to return multiple values. The type of a tuple is the type of its constituent parts:

> var pair = (1,2)
pair: (Int, Int) ...

This can be used to return multiple values from the function; instead of just returning one value, it is possible to return a tuple of values.

Note

Swift also has in-out arguments, which will be seen in the Handling Errors section in Chapter 6, Parsing Networked Data.

Separately, it is also possible to take a variable number of arguments. A function can easily take an array of values with [], but Swift provides a mechanism to allow calling with multiple arguments, using variadic functions. The last argument in a function signature can be variadic, which means that it has ellipses after the type. The value can then be used as an array in the function.

Taken together, these two features allow the creation of a minmax function, which returns both the minimum and maximum from a list of integers:

> func minmax(numbers:Int...) -> (Int,Int) {
.   var min = Int.max
.   var max = Int.min
.   for number in numbers {
.    if number < min {
.     min = number
.    }
.    if number > max {
.     max = number
.    }
.   }
.   return(min,max)
. }
> minmax(1,2,3,4)
$R0: (Int, Int) = {
  0 = 1
  1 = 4
}

The numbers:Int... indicates that a variable number of arguments can be passed into the function. Inside the function, it is processed as an ordinary array; in this case, iterating through using a for...in loop.

Note

The Int.max constant represents the largest Int value, and Int.min is a constant representing the smallest Int value. Similar constants exist for specific integral types, such as UInt8.max and Int64.min.

What if no arguments are passed in? If run on a 64 bit system, then the output will be as follows:

> minmax()
$R1: (Int, Int) = {
  0 = 9223372036854775807
  1 = -9223372036854775808
}

This may not make sense for a minmax function. Instead of returning an error value or a default value, the type system can be used. By making the tuple optional, it is possible to return a nil value if it doesn't exist, or a tuple if it does:

> func minmax(numbers:Int...) -> (Int,Int)? {
.   var min = Int.max
.   var max = Int.min
.   if numbers.count == 0 {
.     return nil
.   } else {
.    for number in numbers {
.     if number < min {
.      min = number
.     } 
.     if number > max {
.      max = number
.     }
.   }
.   return(min,max)
. }
. }
> minmax()
$R2: (Int, Int)? = nil
> mimmax(1,2,3,4)
$R3: (Int, Int)? = (0 = 1, 1 = 3)
> var (minimum,maximum) = minmax(1,2,3,4)!
minimum: Int = 1
maximum: Int = 4

Returning an optional value allows the caller to determine what should happen in cases where the maximum and minimum values are not present.

Tip

If a function does not always have a valid return value, use an optional type to encode that possibility into the type system.

Returning structured values

A tuple is an ordered set of data. The entries in the tuple are ordered, but it can quickly become unclear as to what data is stored, particularly if they are of the same type. In the minmax tuple, it is unclear which value is the minimum and which is the maximum, and this can lead to subtle programming errors later on.

A structure is like a tuple, but with named values. This allows members to be accessed by name instead of by position, leading to fewer errors and greater transparency. Named values can be added to tuples as well. In essence, tuples with named values are anonymous structures.

Tip

Structs are passed in a copy-by-value manner, like tuples. If two variables are assigned the same struct or tuple, then changes to one do not affect the value of another.

A struct is defined with the keyword struct and has variables or values in the body:

> struct MinMax {
.   var min:Int
.   var max:Int
. }

This defines a MinMax type, which can be used in place of any of the types seen so far. It can be used in the minmax function to return a struct instead of a tuple:

> func minmax(numbers:Int…) -> MinMax? {
.   var minmax = MinMax(min:Int.max, max:Int.min)
.   if numbers.count == 0 {
.     return nil
.   } else {
.     for number in numbers {
.       if number < minmax.min {
.         minmax.min = number
.        }
.       if number > minmax.max {
.         minmax.max = number
.       }
.     }
.     return minmax
.   }
. }

The struct is initialized with a type constructor; if MinMax() is used, then the default values for each of the structure members are used (based on the structure definition), but these defaults can be overridden explicitly if desired, with MinMax(min:-10,max:11). For example, if the MinMax struct is defined as struct MinMax { var min:Int = Int.max; var max:Int = Int.min }, then MinMax() would return a structure with the appropriate maximum and minimum values filled in.

Note

When a structure is initialized, all the fields must be assigned. They can be passed in as named arguments in the initializer, or specified in the structure definition.

Swift also has classes; these are covered in the Swift classes section in the next chapter.

Command-line Swift

As Swift can be interpreted, it is possible to use it in shell scripts. By setting the interpreter to swift with a hashbang, the script can be executed without requiring a separate a compilation step. Alternatively, Swift scripts can be compiled to a native executable that can be run without the overhead of an interpreter.

Interpreted Swift scripts

Save the following as hello.swift:

#!/usr/bin/env xcrun swift
println("Hello World")

After saving, make the file executable by running chmod a+x hello.swift. The program can then be run by typing ./hello.swift, and the traditional greeting will be seen:

Hello World

Arguments can be passed in from the command line and interrogated in the process using the Process class through the arguments constant. As with other Unix commands, the first element (0) is the name of the process executable; the arguments passed on in the command line start from one (1).

The program can be terminated using the exit function; however, this is defined in the Foundation framework and so it needs to be imported in order to call this function. Modules in Swift correspond to Frameworks in Objective-C and give access to all functions defined as public API in the module. The syntax to import all elements from a module is import module, although it's also possible to import a single function using import func module.functionName.

A Swift program to print arguments in uppercase can be implemented as follows:

#!/usr/bin/env xcrun swift
import Foundation
let args = Process.arguments[1..<countElements(Process.arguments)]
for arg in args {
  println("\(arg.uppercaseString)")
}
exit(0)

Running this with hello world results in the following:

$ ./upper.swift hello world
HELLO
WORLD

Conventionally, the entry point to Swift programs is via a script called main.swift. If starting a Swift-based command-line application project in Xcode, a main.swift file will be created automatically. Scripts do not need to have a .swift extension. For instance, the previous example could be called upper and it would still work.

Compiled Swift scripts

While interpreted Swift scripts are useful for experimenting and writing, each time the script is started, it is interpreted using the Swift command-line tool and then executed. For simple scripts (such as converting arguments to upper case), this can be a large proportion of the script's execution time.

To compile a Swift script into a native executable, use the swiftc command with the -o output flag to specify a file to write to. This will then generate an executable that does exactly the same as the interpreted script, only much faster. The time command can be used to compare the running time of the interpreted and compiled versions:

$ time ./upper.swift hello world # Interpreted
HELLO
WORLD
real  0m0.145s
$ xcrun swiftc -o upper upper.swift     # Compile step
$ time ./upper hello world       # Compiled
HELLO
WORLD
real  0m0.012s

Of course, the numbers will vary and the initial step only happens once, but startup is very lightweight in Swift. The numbers mentioned earlier are not meant to be taken in magnitude but rather as relative to each other.

The compile step can also be used to link together many individual Swift files into one executable, which helps create a more organized project; Xcode will encourage having multiple Swift files as well.

Summary

The Swift interpreter is a great way of learning how to program in Swift. It allows expressions, statements, and functions to be created and tested along with a command line history that provides editing support.

The basic collection types of arrays and collections and the standard data types, such as strings, numbers, collection types, optional values, and structures were presented. Control flow and functions with positional, named, and variadic arguments, along with default values were also presented. Finally, the ability to write Swift scripts and run them from the command line was also demonstrated.

The next chapter will look at the other way of working with Swift code—through the Xcode playground.

Left arrow icon Right arrow icon

Description

Whether you are a seasoned Objective-C developer or new to the Xcode platform, Swift Essentials will provide you with all you need to know to get started with the language. Prior experience with iOS development is not necessary, but will be helpful to get the most out of the book.

What you will learn

  • Explore the nuts and bolts of the Swift syntax
  • Test Swift code interactively with the REPL
  • Display graphics with QuickLook in the Swift playground
  • Present data in masterdetail applications
  • Use the Swift storyboard to manage multiscreen applications
  • Create graphical UIViews with Swift
  • Parse JSON and XML data from network sources
  • Build a standalone iOS application from start to finish
Estimated delivery fee Deliver to Estonia

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Dec 26, 2014
Length: 228 pages
Edition : 1st
Language : English
ISBN-13 : 9781784396701
Vendor :
Apple
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Estonia

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Publication date : Dec 26, 2014
Length: 228 pages
Edition : 1st
Language : English
ISBN-13 : 9781784396701
Vendor :
Apple
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 125.97
AngularJS Web application development Cookbook
€41.99
Swift Essentials
€41.99
Swift Cookbook
€41.99
Total 125.97 Stars icon
Banner background image

Table of Contents

9 Chapters
1. Exploring Swift Chevron down icon Chevron up icon
2. Playing with Swift Chevron down icon Chevron up icon
3. Creating an iOS Swift App Chevron down icon Chevron up icon
4. Storyboard Applications with Swift and iOS Chevron down icon Chevron up icon
5. Creating Custom Views in Swift Chevron down icon Chevron up icon
6. Parsing Networked Data Chevron down icon Chevron up icon
7. Building a Repository Browser Chevron down icon Chevron up icon
A. Appendix Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.8
(4 Ratings)
5 star 75%
4 star 25%
3 star 0%
2 star 0%
1 star 0%
Charles Nichols Mar 22, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Great book! I've been programming in multiple languages and platforms for years so I mostly skimmed this book for little missing bits and pieces to get me up to speed; the book walks you through the details very well. If you're doing hardcore app development in XCode and know the environment very well, which I don't, it may not be the book for you, but I'd still recommend it as a good walk through paired with Apple's Swift documentation if you have any Swift application development questions; although, you'll likely find what you need online as more people start using it. If you are an occasional Apple developer or new and want to get up to speed in XCode doing application development using Swift this book is a great place to start.
Amazon Verified review Amazon
Matteo Jan 24, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book provides you a learning path from zero to an intermediate complexity iOS app to get the ropes of the language up to a decent level. Every step is explained in extensive detail so that you never feel lost within the code. If you never coded on OSX you won't feel lost as the first chapters provide every little bit you need to start code using xCode playgrounds up to proper iOS/OSX coding. The sole requirement is obviously a recent Mac to do the code demos along with a up-to-date xCode installation.
Amazon Verified review Amazon
Damir Arh Feb 14, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
The author kept the initial introduction to the basic language syntax really brief and quickly made it more interesting and rewarding by replacing the command line REPL environment with Xcode integrated development environment and its playgrounds - a feature which provides a highly interactive environment for experimenting with the language. Not only that: he moved on to development of basic iOS applications, even before he covered all of the language features; introducing many of them only when they were first encountered in sample code.Major part of the book is actually a step by step guide to iOS development in Swift for complete beginners. By the end of it the readers should have enough knowledge to write their first simple iOS application even without any previous experience. Along the way all the key concepts of the API are explained in detail, as well as a couple of peculiarities originating from the Objective-C era which could cause memory leaks or prematurely released memory, if not handled correctly. Even unit testing of Swift code was mentioned and encouraged.The only thing I missed, was a more in-depth discussion of the language features and how they will impact the way the code will be written in it. Though, considering the target audience, it's not really fair to hold that against it. If nothing else, it makes up for it with a very extensive list of resources about Swift and iOS development which should satisfy even the most curious reader.
Amazon Verified review Amazon
Raúl Feb 26, 2015
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
I enjoyed reading this book as it gave me some interesting tips of how to approach swift from another perspective, the command line script/compiled side of the language, which could lead to interesting backend tools that increase developers productivity.Another interesting section I was pleased to read lied within the realm of the playground, a scripting terminal with steroids I would like to call, of which the books explains methodically without going into much detail of the magic behind.With this book, you will learn to do custom views, networking, xml/json parsing, story boards, but the part I considered more important was its whole app as a GIT repository viewer, of course everything handled using swift as core language.However, I consider a big downside that the book does not include any chapters regarding unit test, or advanced swift topics (aka Functional or reactive); being said that, I would recommend it for developers of any platform, for those that have read the Apple swift books.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela