Structs
What you'll learn:
- describe your own type with a struct: properties, default values, creating an instance;
- write methods and explain why a method needs the word
mutating; - add computed properties, the
willSetanddidSetobservers, your owninitandstatic; - explain why changing a copy of a struct leaves the original alone.

Picture a paper form. The header reads Point, and below it are two fields with captions: x and y. A blank form is a template: it says which fields there are and what goes into them. A filled-in form holds data: the field x reads 1, and the field y reads 2.
You can photocopy the form. On the copy, someone crosses out the field x and writes 10, while the original still reads x: 1. Forms filled in from one template each live a life of their own.
Why would a program need such a form? A point on a plane is two numbers, and you could keep them in two variables, x and y. But with ten points you would have twenty variables, and you would have to keep track of which y belongs to which x. It is handier to collect both numbers under one name. That is what structs are for in Swift:
struct Point {
var x: Int
var y: Int
}
let start = Point(x: 1, y: 2)
print(start.x) // 1
print(start.y) // 2
print(start) // Point(x: 1, y: 2)Let's walk through the program step by step:
- The lines from
structto the closing brace describe the template of the formPoint. On their own they create nothing. Point(x: 1, y: 2)fills in a new form: it writes1into the fieldxand2into the fieldy. The finished form goes into the constantstart.start.xandstart.yread the fields through a dot, and the program prints1and2.print(start)prints the whole form: the type name and every field with its value.
Declaring a struct
A struct is your own type that collects several values under one name. The declaration struct Point has three parts:
structis the keyword that starts the declaration;Pointis the name of the new type; type names start with a capital letter, likeIntandString;- the braces hold the fields of the form, each with its own name and type.
The fields of a struct are its properties: as with enums, you read them with a dot and no parentheses. But a struct's property holds a value, and it is declared like an ordinary variable or constant: var x: Int.
You use the new type the same way as Int or String. You can declare a constant of type Point, pass a point to a function or put several points into an array [Point].
Creating an instance
A specific value of type Point, a filled-in form, is called an instance of the struct. To create an instance, you write the type name and, in parentheses, the values of all the properties with labels, like the arguments of a function call. Swift gives a struct this way of creating values on its own: you write nothing for it.
Its rules are these:
- the labels match the property names:
x:andy:; - the order is the same as in the declaration:
Point(y: 2, x: 1)does not compile, with the errorargument 'x' must precede argument 'y'; - every property needs a value:
Point(x: 1)gives the errormissing argument for parameter 'y' in call.
Here the form picture is inaccurate. You can hand in a paper form with a blank field, but an instance of a struct always has all its properties filled in. Swift will not create a Point until it knows both x and y.
Default values
Sometimes a form already has a value printed in, and you change it only when you need to. In a struct, such a value is written right in the property's declaration:
struct Alarm {
var hour = 7
var minute = 30
}
let usual = Alarm()
let early = Alarm(hour: 6)
print(usual) // Alarm(hour: 7, minute: 30)
print(early) // Alarm(hour: 6, minute: 30)A property with a default value can be left out when you create an instance:
Alarm()takes both default values:7hours and30minutes;Alarm(hour: 6)sets the hour and leaves the minutes at their default.
The property types are not written here: Swift infers them from the values, as for an ordinary variable.
Reading and changing through a dot
You read a property through a dot: start.x. You change it through a dot too, if the instance is stored in a var:
var finish = Point(x: 1, y: 2)
finish.x = 10
print(finish) // Point(x: 10, y: 2)finish.x = 10 corrects one field, and y stays as it was.
You can change a property only if two declarations both allow it:
- the instance is declared with
var: in an instance stored in alet, no property can be rewritten; - the property itself is declared with
var: aletproperty does not change even in an instance stored in avar.
Common mistake
A property is changed on an instance declared with let:
start.x = 10 // ✗error: cannot assign to property: 'start' is a 'let' constantThe program does not compile. The constant start is a sealed form: you can change neither the whole form nor single fields, even though x in Point is declared with var. If the form needs corrections, declare the instance with var, like finish.
Key points
- A struct collects several values under one name:
structis followed by the type name and the properties in braces. - An instance is created with labels for all the properties in order:
Point(x: 1, y: 2); a property with a default value can be left out. - A property is read and changed through a dot:
finish.x = 10. - An instance in a
letdoes not change at all: none of its properties can be rewritten.