
Swift is a fantastic way to write software, whether it’s for phones, desktops, servers, or anything else that runs code. It’s a safe, fast, and interactive programming language that combines the best in modern language thinking with wisdom from the wider Apple engineering culture and the diverse contributions from its open-source community. The compiler is optimized for performance and the language is optimized for development, without compromising on either.
Swift is friendly to new programmers. It’s an industrial-quality programming language that’s as expressive and enjoyable as a scripting language. Writing Swift code in a playground lets you experiment with code and see the results immediately, without the overhead of building and running an app.
Swift defines away large classes of common programming errors by adopting modern programming patterns:
- Variables are always initialized before use.
- Array indices are checked for out-of-bounds errors.
- Integers are checked for overflow.
- Optionals ensure that
nil
values are handled explicitly. - Memory is managed automatically.
- Error handling allows controlled recovery from unexpected failures.
Swift code is compiled and optimized to get the most out of modern hardware. The syntax and standard library have been designed based on the guiding principle that the obvious way to write your code should also perform the best. Its combination of safety and speed make Swift an excellent choice for everything from “Hello, world!” to an entire operating system.
Swift combines powerful type inference and pattern matching with a modern, lightweight syntax, allowing complex ideas to be expressed in a clear and concise manner. As a result, code is not just easier to write, but easier to read and maintain as well.
Swift has been years in the making, and it continues 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:
print("Hello, world!") // Prints "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.
var myVariable = 42 myVariable = 50 let myConstant = 42
Control Flow
Use if
and switch
to make conditionals, and use for
–in
, while
, and repeat
–while
to make loops. Parentheses around the condition or loop variable are optional. Braces around the body are required.
let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } print(teamScore) // Prints "11"
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.
let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } print(teamScore) // Prints "11"
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 a value is missing. Write a question mark (?
) after the type of a value to mark the value as optional.
- var optionalString: String? = “Hello”
- print(optionalString == nil)
- // Prints “false”
- var optionalName: String? = “John Appleseed”
- var greeting = “Hello!”
- if let name = optionalName {
- greeting = “Hello, \(name)”
- }
var optionalString: String? = "Hello" print(optionalString == nil) // Prints "false" var optionalName: String? = "John Appleseed" var greeting = "Hello!" if let name = optionalName { greeting = "Hello, \(name)" }
Functions
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.
func greet(person: String, day: String) -> String { return "Hello \(person), today is \(day)." } greet(person: "Bob", day: "Tuesday")
Remove the day
parameter. Add a parameter to include today’s lunch special in the greeting.
By default, functions use their parameter names as labels for their arguments. Write a custom argument label before the parameter name, or write _
to use no argument label.
func greet(_ person: String, on day: String) -> String { return "Hello \(person), today is \(day)." } greet("John", on: "Wednesday")
Use a tuple to make a compound value—for example, to return multiple values from a function. The elements of a tuple can be referred to either by name or by number.
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) { var min = scores[0] var max = scores[0] var sum = 0 for score in scores { if score > max { max = score } else if score < min { min = score } sum += score } return (min, max, sum) } let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9]) print(statistics.sum) // Prints "120" print(statistics.2) // Prints "120"
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.
func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y } returnFifteen()
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.
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
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.
var shape = Shape() shape.numberOfSides = 7 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.
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
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.
class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } let test = Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription()
Make another subclass of NamedShape
called Circle
that takes a radius and a name as arguments to its initializer. Implement an area()
and a simpleDescription()
method on the Circle
class.
In addition to simple properties that are stored, properties can have a getter and a setter.
class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } override func simpleDescription() -> String { return "An equilateral triangle with sides of length \(sideLength)." } } var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle") print(triangle.perimeter) // Prints "9.3" triangle.perimeter = 9.9 print(triangle.sideLength) // Print{"type":"block","srcIndex":56,"srcClientId":"52428f26-e4f6-4879-9e1e-91bc86641830","srcRootClientId":""}s "3.3000000000000003"
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:
Enumerations and Structures
Use enum
to create an enumeration. Like classes and all other named types, enumerations can have methods associated with them.
enum Rank: Int { case ace = 1 case two, three, four, five, six, seven, eight, nine, ten case jack, queen, king func simpleDescription() -> String { switch self { case .ace: return "ace" case .jack: return "jack" case .queen: return "queen" case .king: return "king" default: return String(self.rawValue) } } } let ace = Rank.ace let aceRawValue = ace.rawValue
Write a function that compares two Rank
values by comparing their raw values.
By default, Swift assigns the raw values starting at zero and incrementing by one each time, but you can change this behavior by explicitly specifying values. In the example above, Ace
is explicitly given a raw value of 1
, and 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 rawValue
property to access the raw value of an enumeration case.
Use the init?(rawValue:)
initializer to make an instance of an enumeration from a raw value. It returns either the enumeration case matching the raw value or nil
if there is no matching Rank
.
- if let convertedRank = Rank(rawValue: 3) {
- let threeDescription = convertedRank.simpleDescription()
- }
The case 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.
enum Suit { case spades, hearts, diamonds, clubs func simpleDescription() -> String { switch self { case .spades: return "spades" case .hearts: return "hearts" case .diamonds: return "diamonds" case .clubs: return "clubs" } } } let hearts = Suit.hearts let heartsDescription = hearts.simpleDescription()