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