Structures and Classes

Structures and classes are general-purpose, flexible constructs that become the building blocks of your program's code. You define properties and methods on them just as you would on any other type. The crucial difference — value vs reference semantics — shapes how you design Swift programs, and Swift's bias toward structs is a defining trait of the language.

Comparing structures and classes

Structures and classes in Swift have a lot in common. Both can:

Classes have additional capabilities that structures do not:

Definition syntax

Introduce structures with struct and classes with class. Give types UpperCamelCase names and their members lowerCamelCase names.

struct Resolution {
    var width = 0
    var height = 0
}

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

Creating instances and accessing members

Create an instance by writing the type name followed by parentheses. Access its properties — including nested ones — with dot syntax, and assign to them if the instance is mutable.

let someResolution = Resolution()
let someVideoMode = VideoMode()

print("width is \(someResolution.width)")        // → width is 0
someVideoMode.resolution.width = 1280
print("width is now \(someVideoMode.resolution.width)")  // → 1280

Memberwise initializers for structures

All structures get an automatic memberwise initializer that lets you initialize the member properties by name. Classes do not receive one — you must write your own initializer for a class (covered in the Initialization chapter).

let vga = Resolution(width: 640, height: 480)
print("\(vga.width) × \(vga.height)")   // → 640 × 480

Structures and enumerations are value types

A value type is copied when it's assigned to a variable or constant, or when it's passed to a function. All Swift structures and enumerations are value types — each instance keeps its own independent copy of its data. (So are the standard library's Array, Dictionary, Set, and String.)

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd        // cinema is a COPY of hd
cinema.width = 2048

print(cinema.width)     // → 2048
print(hd.width)         // → 1920 — original is unchanged

Tip: value semantics make code easier to reason about — passing a struct around can't let some far-off code mutate your copy out from under you. This is a big reason SwiftUI models so much state as structs.

Classes are reference types

A reference type is not copied when assigned or passed; instead, the same existing instance is shared. Both names below refer to one VideoMode, so a change through one is visible through the other.

let tenEighty = VideoMode()
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty   // same instance, not a copy
alsoTenEighty.frameRate = 30.0

print(tenEighty.frameRate)        // → 30.0

Note that tenEighty and alsoTenEighty are declared with let, yet you can still change their properties. The constant holds the reference, and that reference never changes — but the instance it points to is mutable.

Identity operators

Because class instances are shared, it's sometimes useful to ask whether two constants refer to the exact same instance. Use the identity operators === (identical to) and !== (not identical to). These differ from ==, which asks whether two values are equal.

if tenEighty === alsoTenEighty {
    print("They refer to the same VideoMode instance.")
}
// → They refer to the same VideoMode instance.

let freshMode = VideoMode()
print(tenEighty === freshMode)   // → false

Note: identity (===) only makes sense for reference types. Value types have no identity — every copy is just as "real" as any other.

Choosing between structures and classes

Apple's guidance for Swift 6 is to use structures by default. Reach for a class only when you have a specific reason. Use a structure when:

Use a class when:

Watch out: under Swift 6 strict concurrency, sharing a mutable class instance across concurrency domains is unsafe unless the type is Sendable or isolated to an actor. Value-type structs sidestep much of this because their copies don't share state — another reason structs are the default.

Recap

Structures and classes share most of Swift's modeling features, but they differ in the one thing that matters most: structs are copied (value semantics) while classes are shared (reference semantics). Master that distinction — and the === identity check — and you'll choose the right tool every time. Next you'll see how both store and compute their data with properties.