Welcome to Swift [605451]
Welcome to Swift
About Swift
Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C,
without the constraints of C compatibility. Swift adopts safe programming patterns and adds modern features to
make programming easier, more flexible, and more fun. Swift’s clean slate, backed by the mature and much-
loved Cocoa and Cocoa Touch frameworks, is an opportunity to reimagine how software development works.
Swift has been years in the making. Apple laid the foundation for Swift by advancing our existing compiler,
debugger, and framework infrastructure. We simplified memory management with Automatic Reference
Counting (ARC). Our framework stack, built on the solid base of Foundation and Cocoa, has been modernized
and standardized throughout. Objective-C itself has evolved to support blocks, collection literals, and modules,
enabling framework adoption of modern language technologies without disruption. Thanks to this groundwork,
we can now introduce a new language for the future of Apple software development.
Swift feels familiar to Objective-C developers. It adopts the readability of Objective-C’s named parameters and
the power of Objective-C’s dynamic object model. It provides seamless access to existing Cocoa frameworks
and mix-and-match interoperability with Objective-C code. Building from this common ground, Swift introduces
many new features and unifies the procedural and object-oriented portions of the language.
Swift is friendly to new programmers. It is the first industrial-quality systems programming language that is as
expressive and enjoyable as a scripting language. It supports playgrounds, an innovative feature that allows
programmers to experiment with Swift code and see the results immediately, without the overhead of building
and running an app.
Swift combines the best in modern language thinking with wisdom from the wider Apple engineering culture.
The compiler is optimized for performance, and the language is optimized for development, without
compromising on either. It’s designed to scale from “hello, world” to an entire operating system. All this makes
Swift a sound future investment for developers and for Apple.
Swift is a fantastic way to write iOS and OS X apps, and will continue to evolve with new features and
capabilities. Our goals for Swift are ambitious. We can’t wait to see what you create with it.
A Swift Tour
Tradition suggests that the first program in a new language should print the words “Hello, world” on the screen.
In Swift, this can be done in a single line:
1
println
(
"Hello, world"
)
If you have written code in C or Objective-C, this syntax looks familiar to you—in Swift, this line of code is a
complete program. You don’t need to import a separate library for functionality like input/output or string
handling. Code written at global scope is used as the entry point for the program, so you don’t need a
main
function. You also don’t need to write semicolons at the end of every statement.
This tour gives you enough information to start writing code in Swift by showing you how to accomplish a
variety of programming tasks. Don’t worry if you don’t understand something—everything introduced in this
tour is explained in detail in the rest of this book.
NOTE
For the best experience, open this chapter as a playground in Xcode. Playgrounds allow you to edit
the code listings and see the result immediately.
Simple Values
Use
let
to make a constant and
var
to make a variable. The value of a constant doesn’t need to be known at
compile time, but you must assign it a value exactly once. This means you can use constants to name a value
that you determine once but use in many places.
1
var
myVariable
=
42
2
myVariable
=
50
3
let
myConstant
=
42
A constant or variable must have the same type as the value you want to assign to it. However, you don’t
always have to write the type explicitly. Providing a value when you create a constant or variable lets the
compiler infer its type. In the example above, the compiler infers that
myVariable
is an integer because its
initial value is a integer.
If the initial value doesn’t provide enough information (or if there is no initial value), specify the type by writing it
after the variable, separated by a colon.
1
let
implicitInteger
=
70
2
let
implicitDouble
=
70.0
3
let
explicitDouble
:
Double
=
70
EXPERIMENT
Create a constant with an explicit type of
Float
and a value of
4
.
Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly
make an instance of the desired type.
1
let
label
=
"The width is "
2
let
width
=
94
3
let
widthLabel
=
label
+
String
(
width
)
EXPERIMENT
Try removing the conversion to
String
from the last line. What error do you get?
There’s an even simpler way to include values in strings: Write the value in parentheses, and write a backslash
(
\
) before the parentheses. For example:
1
let
apples
=
3
2
let
oranges
=
5
3
let
appleSummary
=
"I have
\(
apples
)
apples."
4
let
fruitSummary
=
"I have
\(
apples
+
oranges
)
pieces of fruit."
EXPERIMENT
Use
\()
to include a floating-point calculation in a string and to include someone’s name in a
greeting.
Create arrays and dictionaries using brackets (
[]
), and access their elements by writing the index or key in
brackets.
1
var
shoppingList
= [
"catfish"
,
"water"
,
"tulips"
,
"blue paint"
]
2
shoppingList
[
1
] =
"bottle of water"
3
4
var
occupations
= [
5
"Malcolm"
:
"Captain"
,
6
"Kaylee"
:
"Mechanic"
,
7
]
8
occupations
[
"Jayne"
] =
"Public Relations"
To create an empty array or dictionary, use the initializer syntax.
1
let
emptyArray
=
String
[]()
2
let
emptyDictionary
=
Dictionary
<
String
,
Float
>()
If type information can be inferred, you can write an empty array as
[]
and an empty dictionary as
[:]
—for
example, when you set a new value for a variable or pass an argument to a function.
1
shoppingList
= []
// Went shopping and bought everything.
Control Flow
Use
if
and
switch
to make conditionals, and use
for
–
in
,
for
,
while
, and
do
–
while
to make loops.
Parentheses around the condition or loop variable are optional. Braces around the body are required.
1
let
individualScores
= [
75
,
43
,
103
,
87
,
12
]
2
var
teamScore
=
0
3
for
score
in
individualScores
{
4
if
score
>
50
{
5
teamScore
+=
3
6
}
else
{
7
teamScore
+=
1
8
}
9
}
10
teamScore
In an
if
statement, the conditional must be a Boolean expression—this means that code such as
if score
{ … }
is an error, not an implicit comparison to zero.
You can use
if
and
let
together to work with values that might be missing. These values are represented as
optionals. An optional value either contains a value or contains
nil
to indicate that the value is missing. Write a
question mark (
?
) after the type of a value to mark the value as optional.
1
var
optionalString
:
String
? =
"Hello"
2
optionalString
==
nil
3
4
var
optionalName
:
String
? =
"John Appleseed"
5
var
greeting
=
"Hello!"
6
if
let
name
=
optionalName
{
7
greeting
=
"Hello,
\(
name
)
"
8
}
EXPERIMENT
Change
optionalName
to
nil
. What greeting do you get? Add an
else
clause that sets a
different greeting if
optionalName
is
nil
.
If the optional value is
nil
, the conditional is
false
and the code in braces is skipped. Otherwise, the optional
value is unwrapped and assigned to the constant after
let
, which makes the unwrapped value available inside
the block of code.
Switches support any kind of data and a wide variety of comparison operations—they aren’t limited to integers
and tests for equality.
1
let
vegetable
=
"red pepper"
2
switch
vegetable
{
3
case
"celery"
:
4
let
vegetableComment
=
"Add some raisins and make ants on a log."
5
case
"cucumber"
,
"watercress"
:
6
let
vegetableComment
=
"That would make a good tea sandwich."
7
case
let
x
where
x
.
hasSuffix
(
"pepper"
):
8
let
vegetableComment
=
"Is it a spicy
\(
x
)
?"
9
default
:
10
let
vegetableComment
=
"Everything tastes good in soup."
11
}
EXPERIMENT
Try removing the default case. What error do you get?
After executing the code inside the switch case that matched, the program exits from the switch statement.
Execution doesn’t continue to the next case, so there is no need to explicitly break out of the switch at the end of
each case’s code.
You use
for
–
in
to iterate over items in a dictionary by providing a pair of names to use for each key-value
pair.
1
let
interestingNumbers
= [
2
"Prime"
: [
2
,
3
,
5
,
7
,
11
,
13
],
3
"Fibonacci"
: [
1
,
1
,
2
,
3
,
5
,
8
],
4
"Square"
: [
1
,
4
,
9
,
16
,
25
],
5
]
6
var
largest
=
0
7
for
(
kind
,
numbers
)
in
interestingNumbers
{
8
for
number
in
numbers
{
9
if
number
>
largest
{
10
largest
=
number
11
}
12
}
13
}
14
largest
EXPERIMENT
Add another variable to keep track of which kind of number was the largest, as well as what that
largest number was.
Use
while
to repeat a block of code until a condition changes. The condition of a loop can be at the end instead,
ensuring that the loop is run at least once.
1
var
n
=
2
2
while
n
<
100
{
3
n
=
n
*
2
4
}
5
n
6
7
var
m
=
2
8
do
{
9
m
=
m
*
2
10
}
while
m
<
100
11
m
You can keep an index in a loop—either by using
..
to make a range of indexes or by writing an explicit
initialization, condition, and increment. These two loops do the same thing:
1
var
firstForLoop
=
0
2
for
i
in
0
..
3
{
3
firstForLoop
+=
i
4
}
5
firstForLoop
6
7
var
secondForLoop
=
0
8
for
var
i
=
0
;
i
<
3
; ++
i
{
9
secondForLoop
+=
1
10
}
11
secondForLoop
Use
..
to make a range that omits its upper value, and use
…
to make a range that includes both values.
Functions and Closures
Use
func
to declare a function. Call a function by following its name with a list of arguments in parentheses.
Use
->
to separate the parameter names and types from the function’s return type.
1
func
greet
(
name
:
String
,
day
:
String
) ->
String
{
2
return
"Hello
\(
name
)
, today is
\(
day
)
."
3
}
4
greet
(
"Bob"
,
"Tuesday"
)
EXPERIMENT
Remove the
day
parameter. Add a parameter to include today’s lunch special in the greeting.
Use a tuple to return multiple values from a function.
1
func
getGasPrices
() -> (
Double
,
Double
,
Double
) {
2
return
(
3.59
,
3.69
,
3.79
)
3
}
4
getGasPrices
()
Functions can also take a variable number of arguments, collecting them into an array.
1
func
sumOf
(
numbers
:
Int
…) ->
Int
{
2
var
sum
=
0
3
for
number
in
numbers
{
4
sum
+=
number
5
}
6
return
sum
7
}
8
sumOf
()
9
sumOf
(
42
,
597
,
12
)
EXPERIMENT
Write a function that calculates the average of its arguments.
Functions can be nested. Nested functions have access to variables that were declared in the outer function.
You can use nested functions to organize the code in a function that is long or complex.
1
func
returnFifteen
() ->
Int
{
2
var
y
=
10
3
func
add
() {
4
y
+=
5
5
}
6
add
()
7
return
y
8
}
9
returnFifteen
()
Functions are a first-class type. This means that a function can return another function as its value.
1
func
makeIncrementer
() -> (
Int
->
Int
) {
2
func
addOne
(
number
:
Int
) ->
Int
{
3
return
1
+
number
4
}
5
return
addOne
6
}
7
var
increment
=
makeIncrementer
()
8
increment
(
7
)
A function can take another function as one of its arguments.
1
func
hasAnyMatches
(
list
:
Int
[],
condition
:
Int
->
Bool
) ->
Bool
{
2
for
item
in
list
{
3
if
condition
(
item
) {
4
return
true
5
}
6
}
7
return
false
8
}
9
func
lessThanTen
(
number
:
Int
) ->
Bool
{
10
return
number
<
10
11
}
12
var
numbers
= [
20
,
19
,
7
,
12
]
13
hasAnyMatches
(
numbers
,
lessThanTen
)
Functions are actually a special case of closures. You can write a closure without a name by surrounding code
with braces (
{}
). Use
in
to separate the arguments and return type from the body.
1
numbers
.
map
({
2
(
number
:
Int
) ->
Int
in
3
let
result
=
3
*
number
4
return
result
5
})
EXPERIMENT
Rewrite the closure to return zero for all odd numbers.
You have several options for writing closures more concisely. When a closure’s type is already known, such as
the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement
closures implicitly return the value of their only statement.
1
numbers
.
map
({
number
in
3
*
number
})
You can refer to parameters by number instead of by name—this approach is especially useful in very short
closures. A closure passed as the last argument to a function can appear immediately after the parentheses.
1
sort
([
1
,
5
,
3
,
12
,
2
]) {
$0
>
$1
}
Objects and Classes
Use
class
followed by the class’s name to create a class. A property declaration in a class is written the
same way as a constant or variable declaration, except that it is in the context of a class. Likewise, method and
function declarations are written the same way.
1
class
Shape
{
2
var
numberOfSides
=
0
3
func
simpleDescription
() ->
String
{
4
return
"A shape with
\(
numberOfSides
)
sides."
5
}
6
}
EXPERIMENT
Add a constant property with
let
, and add another method that takes an argument.
Create an instance of a class by putting parentheses after the class name. Use dot syntax to access the
properties and methods of the instance.
1
var
shape
=
Shape
()
2
shape
.
numberOfSides
=
7
3
var
shapeDescription
=
shape
.
simpleDescription
()
This version of the
Shape
class is missing something important: an initializer to set up the class when an
instance is created. Use
init
to create one.
1
class
NamedShape
{
2
var
numberOfSides
:
Int
=
0
3
var
name
:
String
4
5
init
(
name
:
String
) {
6
self
.
name
=
name
7
}
8
9
func
simpleDescription
() ->
String
{
10
return
"A shape with
\(
numberOfSides
)
sides."
11
}
12
}
Notice how
self
is used to distinguish the
name
property from the
name
argument to the initializer. The
arguments to the initializer are passed like a function call when you create an instance of the class. Every
property needs a value assigned—either in its declaration (as with
numberOfSides
) or in the initializer (as
with
name
).
Use
deinit
to create a deinitializer if you need to perform some cleanup before the object is deallocated.
Subclasses include their superclass name after their class name, separated by a colon. There is no
requirement for classes to subclass any standard root class, so you can include or omit a superclass as
needed.
Methods on a subclass that override the superclass’s implementation are marked with
override
—overriding
a method by accident, without
override
, is detected by the compiler as an error. The compiler also detects
methods with
override
that don’t actually override any method in the superclass.
1
class
Square
:
NamedShape
{
2
var
sideLength
:
Double
3
4
init
(
sideLength
:
Double
,
name
:
String
) {
5
self
.
sideLength
=
sideLength
6
super
.
init
(
name
:
name
)
7
numberOfSides
=
4
8
}
9
10
func
area
() ->
Double
{
11
return
sideLength
*
sideLength
12
}
13
14
override
func
simpleDescription
() ->
String
{
15
return
"A square with sides of length
\(
sideLength
)
."
16
}
17
}
18
let
test
=
Square
(
sideLength
:
5.2
,
name
:
"my test square"
)
19
test
.
area
()
20
test
.
simpleDescription
()
EXPERIMENT
Make another subclass of
NamedShape
called
Circle
that takes a radius and a name as
arguments to its initializer. Implement an
area
and a
describe
method on the
Circle
class.
In addition to simple properties that are stored, properties can have a getter and a setter.
1
class
EquilateralTriangle
:
NamedShape
{
2
var
sideLength
:
Double
=
0.0
3
4
init
(
sideLength
:
Double
,
name
:
String
) {
5
self
.
sideLength
=
sideLength
6
super
.
init
(
name
:
name
)
7
numberOfSides
=
3
8
}
9
10
var
perimeter
:
Double
{
11
get
{
12
return
3.0
*
sideLength
13
}
14
set
{
15
sideLength
=
newValue
/
3.0
16
}
17
}
18
19
override
func
simpleDescription
() ->
String
{
20
return
"An equilateral triagle with sides of length
\
(
sideLength
)
."
21
}
22
}
23
var
triangle
=
EquilateralTriangle
(
sideLength
:
3.1
,
name
:
"a
triangle"
)
24
triangle
.
perimeter
25
triangle
.
perimeter
=
9.9
26
triangle
.
sideLength
In the setter for
perimeter
, the new value has the implicit name
newValue
. You can provide an explicit
name in parentheses after
set
.
Notice that the initializer for the
EquilateralTriangle
class has three different steps:
1
.
Setting the value of properties that the subclass declares.
2
.
Calling the superclass’s initializer.
3
.
Changing the value of properties defined by the superclass. Any additional setup work that uses
methods, getters, or setters can also be done at this point.
If you don’t need to compute the property but still need to provide code that is run before and after setting a new
value, use
willSet
and
didSet
. For example, the class below ensures that the side length of its triangle is
always the same as the side length of its square.
1
class
TriangleAndSquare
{
2
var
triangle
:
EquilateralTriangle
{
3
willSet
{
4
square
.
sideLength
=
newValue
.
sideLength
5
}
6
}
7
var
square
:
Square
{
8
willSet
{
9
triangle
.
sideLength
=
newValue
.
sideLength
10
}
11
}
12
init
(
size
:
Double
,
name
:
String
) {
13
square
=
Square
(
sideLength
:
size
,
name
:
name
)
14
triangle
=
EquilateralTriangle
(
sideLength
:
size
,
name
:
name
)
15
}
16
}
17
var
triangleAndSquare
=
TriangleAndSquare
(
size
:
10
,
name
:
"another test shape"
)
18
triangleAndSquare
.
square
.
sideLength
19
triangleAndSquare
.
triangle
.
sideLength
20
triangleAndSquare
.
square
=
Square
(
sideLength
:
50
,
name
:
"larger
square"
)
21
triangleAndSquare
.
triangle
.
sideLength
Methods on classes have one important difference from functions. Parameter names in functions are used only
within the function, but parameters names in methods are also used when you call the method (except for the
first parameter). By default, a method has the same name for its parameters when you call it and within the
method itself. You can specify a second name, which is used inside the method.
1
class
Counter
{
2
var
count
:
Int
=
0
3
func
incrementBy
(
amount
:
Int
,
numberOfTimes
times
:
Int
) {
4
count
+=
amount
*
times
5
}
6
}
7
var
counter
=
Counter
()
8
counter
.
incrementBy
(
2
,
numberOfTimes
:
7
)
When working with optional values, you can write
?
before operations like methods, properties, and
subscripting. If the value before the
?
is
nil
, everything after the
?
is ignored and the value of the whole
expression is
nil
. Otherwise, the optional value is unwrapped, and everything after the
?
acts on the
unwrapped value. In both cases, the value of the whole expression is an optional value.
1
let
optionalSquare
:
Square
? =
Square
(
sideLength
:
2.5
,
name
:
"optional
square"
)
2
let
sideLength
=
optionalSquare
?.
sideLength
Enumerations and Structures
Use
enum
to create an enumeration. Like classes and all other named types, enumerations can have methods
associated with them.
1
enum
Rank
:
Int
{
2
case
Ace
=
1
3
case
Two
,
Three
,
Four
,
Five
,
Six
,
Seven
,
Eight
,
Nine
,
Ten
4
case
Jack
,
Queen
,
King
5
func
simpleDescription
() ->
String
{
6
switch
self
{
7
case
.
Ace
:
8
return
"ace"
9
case
.
Jack
:
10
return
"jack"
11
case
.
Queen
:
12
return
"queen"
13
case
.
King
:
14
return
"king"
15
default
:
16
return
String
(
self
.
toRaw
())
17
}
18
}
19
}
20
let
ace
=
Rank
.
Ace
21
let
aceRawValue
=
ace
.
toRaw
()
EXPERIMENT
Write a function that compares two
Rank
values by comparing their raw values.
In the example above, the raw value type of the enumeration is
Int
, so you only have to specify the first raw
value. The rest of the raw values are assigned in order. You can also use strings or floating-point numbers as
the raw type of an enumeration.
Use the
toRaw
and
fromRaw
functions to convert between the raw value and the enumeration value.
1
if
let
convertedRank
=
Rank
.
fromRaw
(
3
) {
2
let
threeDescription
=
convertedRank
.
simpleDescription
()
3
}
The member values of an enumeration are actual values, not just another way of writing their raw values. In
fact, in cases where there isn’t a meaningful raw value, you don’t have to provide one.
1
enum
Suit
{
2
case
Spades
,
Hearts
,
Diamonds
,
Clubs
3
func
simpleDescription
() ->
String
{
4
switch
self
{
5
case
.
Spades
:
6
return
"spades"
7
case
.
Hearts
:
8
return
"hearts"
9
case
.
Diamonds
:
10
return
"diamonds"
11
case
.
Clubs
:
12
return
"clubs"
13
}
14
}
15
}
16
let
hearts
=
Suit
.
Hearts
17
let
heartsDescription
=
hearts
.
simpleDescription
()
EXPERIMENT
Add a
color
method to
Suit
that returns “black” for spades and clubs, and returns “red” for hearts
and diamonds.
Notice the two ways that the
Hearts
member of the enumeration is referred to above: When assigning a value
to the
hearts
constant, the enumeration member
Suit.Hearts
is referred to by its full name because the
constant doesn’t have an explicit type specified. Inside the switch, the enumeration is referred to by the
abbreviated form
.Hearts
because the value of
self
is already known to be a suit. You can use the
abbreviated form anytime the value’s type is already known.
Use
struct
to create a structure. Structures support many of the same behaviors as classes, including
methods and initializers. One of the most important differences between structures and classes is that
structures are always copied when they are passed around in your code, but classes are passed by reference.
1
struct
Card
{
2
var
rank
:
Rank
3
var
suit
:
Suit
4
func
simpleDescription
() ->
String
{
5
return
"The
\(
rank
.
simpleDescription
())
of
\
(
suit
.
simpleDescription
())
"
6
}
7
}
8
let
threeOfSpades
=
Card
(
rank
: .
Three
,
suit
: .
Spades
)
9
let
threeOfSpadesDescription
=
threeOfSpades
.
simpleDescription
()
EXPERIMENT
Add a method to
Card
that creates a full deck of cards, with one card of each combination of rank
and suit.
An instance of an enumeration member can have values associated with the instance. Instances of the same
enumeration member can have different values associated with them. You provide the associated values when
you create the instance. Associated values and raw values are different: The raw value of an enumeration
member is the same for all of its instances, and you provide the raw value when you define the enumeration.
For example, consider the case of requesting the sunrise and sunset time from a server. The server either
responds with the information or it responds with some error information.
1
enum
ServerResponse
{
2
case
Result
(
String
,
String
)
3
case
Error
(
String
)
4
}
5
6
let
success
=
ServerResponse
.
Result
(
"6:00 am"
,
"8:09 pm"
)
7
let
failure
=
ServerResponse
.
Error
(
"Out of cheese."
)
8
9
switch
success
{
10
case
let
.
Result
(
sunrise
,
sunset
):
11
let
serverResponse
=
"Sunrise is at
\(
sunrise
)
and sunset
is at
\(
sunset
)
."
12
case
let
.
Error
(
error
):
13
let
serverResponse
=
"Failure…
\(
error
)
"
14
}
EXPERIMENT
Add a third case to
ServerResponse
and to the switch.
Notice how the sunrise and sunset times are extracted from the
ServerResponse
value as part of matching
the value against the switch cases.
Protocols and Extensions
Use
protocol
to declare a protocol.
1
protocol
ExampleProtocol
{
2
var
simpleDescription
:
String
{
get
}
3
mutating
func
adjust
()
4
}
Classes, enumerations, and structs can all adopt protocols.
1
class
SimpleClass
:
ExampleProtocol
{
2
var
simpleDescription
:
String
=
"A very simple class."
3
var
anotherProperty
:
Int
=
69105
4
func
adjust
() {
5
simpleDescription
+=
" Now 100% adjusted."
6
}
7
}
8
var
a
=
SimpleClass
()
9
a
.
adjust
()
10
let
aDescription
=
a
.
simpleDescription
11
12
struct
SimpleStructure
:
ExampleProtocol
{
13
var
simpleDescription
:
String
=
"A simple structure"
14
mutating
func
adjust
() {
15
simpleDescription
+=
" (adjusted)"
16
}
17
}
18
var
b
=
SimpleStructure
()
19
b
.
adjust
()
20
let
bDescription
=
b
.
simpleDescription
EXPERIMENT
Write an enumeration that conforms to this protocol.
Notice the use of the
mutating
keyword in the declaration of
SimpleStructure
to mark a method that
modifies the structure. The declaration of
SimpleClass
doesn’t need any of its methods marked as mutating
because methods on a class can always modify the class.
Use
extension
to add functionality to an existing type, such as new methods and computed properties. You
can use an extension to add protocol conformance to a type that is declared elsewhere, or even to a type that
you imported from a library or framework.
1
extension
Int
:
ExampleProtocol
{
2
var
simpleDescription
:
String
{
3
return
"The number
\(
self
)
"
4
}
5
mutating
func
adjust
() {
6
self
+=
42
7
}
8
}
9
7
.
simpleDescription
EXPERIMENT
Write an extension for the
Double
type that adds an
absoluteValue
property.
You can use a protocol name just like any other named type—for example, to create a collection of objects that
have different types but that all conform to a single protocol. When you work with values whose type is a
protocol type, methods outside the protocol definition are not available.
1
let
protocolValue
:
ExampleProtocol
=
a
2
protocolValue
.
simpleDescription
3
// protocolValue.anotherProperty // Uncomment to see the error
Even though the variable
protocolValue
has a runtime type of
SimpleClass
, the compiler treats it as the
given type of
ExampleProtocol
. This means that you can’t accidentally access methods or properties that
the class implements in addition to its protocol conformance.
Generics
Write a name inside angle brackets to make a generic function or type.
1
func
repeat
<
ItemType
>(
item
:
ItemType
,
times
:
Int
) ->
ItemType
[] {
2
var
result
=
ItemType
[]()
3
for
i
in
0
..
times
{
4
result
+=
item
5
}
6
return
result
7
}
8
repeat
(
"knock"
,
4
)
You can make generic forms of functions and methods, as well as classes, enumerations, and structures.
1
// Reimplement the Swift standard library's optional type
2
enum
OptionalValue
<
T
> {
3
case
None
4
case
Some
(
T
)
5
}
6
var
possibleInteger
:
OptionalValue
<
Int
> = .
None
7
possibleInteger
= .
Some
(
100
)
Use
where
after the type name to specify a list of requirements—for example, to require the type to implement
a protocol, to require two types to be the same, or to require a class to have a particular superclass.
1
func
anyCommonElements
<
T
,
U
where
T
:
Sequence
,
U
:
Sequence
,
T
.
GeneratorType
.
Element
:
Equatable
,
T
.
GeneratorType
.
Element
==
U
.
GeneratorType
.
Element
>
(
lhs
:
T
,
rhs
:
U
) ->
Bool
{
2
for
lhsItem
in
lhs
{
3
for
rhsItem
in
rhs
{
4
if
lhsItem
==
rhsItem
{
5
return
true
6
}
7
}
8
}
9
return
false
10
}
11
anyCommonElements
([
1
,
2
,
3
], [
3
])
EXPERIMENT
Modify the
anyCommonElements
function to make a function that returns an array of the
elements that any two sequences have in common.
In the simple cases, you can omit
where
and simply write the protocol or class name after a colon. Writing
<T: Equatable>
is the same as writing
<T where T: Equatable>
.
Language Guide
The Basics
Swift is a new programming language for iOS and OS X app development. Nonetheless, many parts of Swift
will be familiar from your experience of developing in C and Objective-C.
Swift provides its own versions of all fundamental C and Objective-C types, including
Int
for integers;
Double
and
Float
for floating-point values;
Bool
for Boolean values; and
String
for textual data. Swift
also provides powerful versions of the two primary collection types,
Array
and
Dictionary
, as described
in
Collection Types
.
Like C, Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use
of variables whose values cannot be changed. These are known as constants, and are much more powerful
than constants in C. Constants are used throughout Swift to make code safer and clearer in intent when you
work with values that do not need to change.
In addition to familiar types, Swift introduces advanced types not found in Objective-C. These include tuples,
which enable you to create and pass around groupings of values. Tuples can return multiple values from a
function as a single compound value.
Swift also introduces optional types, which handle the absence of a value. Optionals say either “there
is
a value,
and it equals
x
” or “there
isn’t
a value at all”. Optionals are similar to using
nil
with pointers in Objective-C,
but they work for any type, not just classes. Optionals are safer and more expressive than
nil
pointers in
Objective-C and are at the heart of many of Swift’s most powerful features.
Optionals are an example of the fact that Swift is a
type safe
language. Swift helps you to be clear about the
types of values your code can work with. If part of your code expects a
String
, type safety prevents you from
passing it an
Int
by mistake. This enables you to catch and fix errors as early as possible in the development
process.
Constants and Variables
Constants and variables associate a name (such as
maximumNumberOfLoginAttempts
or
welcomeMessage
) with a value of a particular type (such as the number
10
or the string
"Hello"
). The
value of a
constant
cannot be changed once it is set, whereas a
variable
can be set to a different value in the
future.
Declaring Constants and Variables
Constants and variables must be declared before they are used. You declare constants with the
let
keyword
and variables with the
var
keyword. Here’s an example of how constants and variables can be used to track
the number of login attempts a user has made:
1
let
maximumNumberOfLoginAttempts
=
10
2
var
currentLoginAttempt
=
0
This code can be read as:
“Declare a new constant called
maximumNumberOfLoginAttempts
, and give it a value of
10
. Then,
declare a new variable called
currentLoginAttempt
, and give it an initial value of
0
.”
In this example, the maximum number of allowed login attempts is declared as a constant, because the
maximum value never changes. The current login attempt counter is declared as a variable, because this value
must be incremented after each failed login attempt.
You can declare multiple constants or multiple variables on a single line, separated by commas:
1
var
x
=
0.0
,
y
=
0.0
,
z
=
0.0
NOTE
If a stored value in your code is not going to change, always declare it as a constant with the
let
keyword. Use variables only for storing values that need to be able to change.
Type Annotations
You can provide a
type annotation
when you declare a constant or variable, to be clear about the kind of values
the constant or variable can store. Write a type annotation by placing a colon after the constant or variable
name, followed by a space, followed by the name of the type to use.
This example provides a type annotation for a variable called
welcomeMessage
, to indicate that the variable
can store
String
values:
1
var
welcomeMessage
:
String
The colon in the declaration means
“…of type…,”
so the code above can be read as:
“Declare a variable called
welcomeMessage
that is of type
String
.”
The phrase “of type
String
” means “can store any
String
value.” Think of it as meaning “the type of thing”
(or “the kind of thing”) that can be stored.
The
welcomeMessage
variable can now be set to any string value without error:
1
welcomeMessage
=
"Hello"
NOTE
It is rare that you need to write type annotations in practice. If you provide an initial value for a
constant or variable at the point that it is defined, Swift can almost always infer the type to be used
for that constant or variable, as described in
Type Safety and Type Inference
. In the
welcomeMessage
example above, no initial value is provided, and so the type of the
welcomeMessage
variable is specified with a type annotation rather than being inferred from an
initial value.
Naming Constants and Variables
You can use almost any character you like for constant and variable names, including Unicode characters:
1
let
π
=
3.14159
2
let
你好
=
"
你好世界
"
3
let
=
"dogcow"
Constant and variable names cannot contain mathematical symbols, arrows, private-use (or invalid) Unicode
code points, or line- and box-drawing characters. Nor can they begin with a number, although numbers may be
included elsewhere within the name.
Once you’ve declared a constant or variable of a certain type, you can’t redeclare it again with the same name,
or change it to store values of a different type. Nor can you change a constant into a variable or a variable into a
constant.
NOTE
If you need to give a constant or variable the same name as a reserved Swift keyword, you can do
so by surrounding the keyword with back ticks (
`
) when using it as a name. However, you should
avoid using keywords as names unless you have absolutely no choice.
You can change the value of an existing variable to another value of a compatible type. In this example, the value
of
friendlyWelcome
is changed from
"Hello!"
to
"Bonjour!"
:
1
var
friendlyWelcome
=
"Hello!"
2
friendlyWelcome
=
"Bonjour!"
3
// friendlyWelcome is now "Bonjour!"
Unlike a variable, the value of a constant cannot be changed once it is set. Attempting to do so is reported as an
error when your code is compiled:
1
let
languageName
=
"Swift"
2
languageName
=
"Swift++"
3
// this is a compile-time error – languageName cannot be changed
Printing Constants and Variables
You can print the current value of a constant or variable with the
println
function:
1
println
(
friendlyWelcome
)
2
// prints "Bonjour!"
println
is a global function that prints a value, followed by a line break, to an appropriate output. If you are
working in Xcode, for example,
println
prints its output in Xcode’s “console” pane. (A second function,
print
, performs the same task without appending a line break to the end of the value to be printed.)
The
println
function prints any
String
value you pass to it:
1
println
(
"This is a string"
)
2
// prints "This is a string"
The
println
function can print more complex logging messages, in a similar manner to Cocoa’s
NSLog
function. These messages can include the current values of constants and variables.
Swift uses
string interpolation
to include the name of a constant or variable as a placeholder in a longer string,
and to prompt Swift to replace it with the current value of that constant or variable. Wrap the name in
parentheses and escape it with a backslash before the opening parenthesis:
1
println
(
"The current value of friendlyWelcome is
\(
friendlyWelcome
)
"
)
2
// prints "The current value of friendlyWelcome is Bonjour!"
NOTE
All options you can use with string interpolation are described in
String Interpolation
.
Comments
Use comments to include non-executable text in your code, as a note or reminder to yourself. Comments are
ignored by the Swift compiler when your code is compiled.
Comments in Swift are very similar to comments in C. Single-line comments begin with two forward-slashes
(
//
):
1
// this is a comment
You can also write multiline comments, which start with a forward-slash followed by an asterisk (
/*
) and end
with an asterisk followed by a forward-slash (
*/
):
1
/* this is also a comment,
2
but written over multiple lines */
Unlike multiline comments in C, multiline comments in Swift can be nested inside other multiline comments.
You write nested comments by starting a multiline comment block and then starting a second multiline
comment within the first block. The second block is then closed, followed by the first block:
1
/* this is the start of the first multiline comment
2
/* this is the second, nested multiline comment */
3
this is the end of the first multiline comment */
Nested multiline comments enable you to comment out large blocks of code quickly and easily, even if the code
already contains multiline comments.
Semicolons
Unlike many other languages, Swift does not require you to write a semicolon (
;
) after each statement in your
code, although you can do so if you wish. Semicolons
are
required, however, if you want to write multiple
separate statements on a single line:
1
let
cat
=
"
